Cómo obtener la fecha actual y el huso horario en formato de números

Quiero imprimir la fecha actual en este formato 2017/06/05 > Year/Month/Day y junto a él, la zona horaria actual en este formato +3

He utilizado este código

 String DateToday = DateFormat.getDateInstance().format(new Date()); String TZtoday = DateFormat.getTimeInstance().getTimeZone().getDisplayName(); txt.setText(DateToday + " | "+ TZtoday ); 

Pero, se muestra así:

Jun 5, 2017 | Hora estándar de Arabia

Lo quiero así:

2017/06/05 | +3

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd | X"); System.out.println(sdf.format(new Date())); 

se acerca, pero la zona horaria se imprime con un cero a la izquierda:

 2017/06/05 | +03 

Supongo que podría eliminar los ceros principales de la zona horaria, si es necesario:

 SimpleDateFormat date = new SimpleDateFormat("yyyy/MM/dd"); SimpleDateFormat zone = new SimpleDateFormat("ZZZZZ"); // = +03:00 String tz = zone.format(new Date()).split(":")[0] .replaceAll("^(\\+|-)0", "$1"); // = +3 System.out.println(sdf.format(new Date()) + " | " + tz); 

lo que da:

 2017/06/05 | +3 

Sé que estás en Android, y sé que lo que se ofrece incorporado en Android son las clases anticuadas como DateFormat , SimpleDateFormat , Date y Calendar . Todavía digo, si usted está haciendo algo con fechas y / o tiempos y / o zonas horarias, usted debe considerar seriamente saltar estas clases y pasar a sus reemplazos modernos. Esto requerirá que obtenga ThreeTenABP . Entonces sugiero de esta manera:

  ZonedDateTime date = ZonedDateTime.now(ZoneId.systemDefault()); String tzToday = date.format(DateTimeFormatter.ofPattern("uuuu/MM/dd | x")); tzToday = tzToday.replaceFirst("(?<=\\+|-)0", ""); 

Resultado en mi computadora:

 2017/06/05 | +2 

Resultado en la zona horaria de Asia / Katmandú puede no ser exactamente lo que quería:

 2017/06/05 | +545 

Usted puede pensar que mi fragmento de código no es muy ventajoso sobre el uso de las antiguas clases. Usted puede tomar mi palabra cuando digo que hay tantos casos donde las clases viejas le dan sorpresas negativas, por lo que cuanto antes pueda empezar a usar los nuevos, mejor. O puede hacer un error tipográfico en la cadena de patrón de formato, por ejemplo, y observe cómo obtiene un resultado sorprendente con las clases antiguas sin signo de que algo está mal, mientras que las más nuevas intentarán juntar un mensaje de error significativo.

Otro detalle a tener en cuenta es que estoy leyendo el reloj del sistema y la zona horaria de JVM sólo una vez (pasando la zona horaria de nuevo a now() para asegurarse de que se utiliza para el tiempo). Su código en la pregunta formatea la fecha primero, luego lee la zona horaria. Si alguien cambia la zona horaria entre los dos, el resultado será inconsistente. Muy poco probable, pero esto también significa que será muy poco probable que alguien será capaz de averiguar lo que pasó.

El (?<=\\+|-) en la expresión regular es un lookbehind: Estoy reemplazando un 0 precedido por + o - con la cadena vacía. Busqué en vano una forma de formatear el desplazamiento de la zona como +3 como replaceFirst , así que recurrí al método replaceFirst .

Enlace adicional: Cómo utilizar ThreeTenABP en Android Project .

Simplemente complementando la respuesta de @Ole VV , he encontrado otra forma de hacerlo usando ThreeTenABP , pero sin necesidad de un reemplazo de regex (aunque no creo que sea mucho más simple, más sobre eso a continuación).

Utilizando el DateTimeFormatterBuilder puede utilizar un HashMap que asigna los valores de los desplazamientos a una String . Por lo tanto, para horas completas de desplazamiento (como +03:00 ), puede asignar el valor respectivo a la cadena +3 y así sucesivamente.

El único problema es que el ZoneOffset tiene precisión segundos . Y los valores mínimo y máximo son, respectivamente, UTC-18:00:00 y UTC+18:00:00 . Así que todos los valores posibles son UTC-18:00:00 , UTC-17:59:59 , UTC-17:59:58 y así sucesivamente. Y el formateador requiere que todos los valores posibles se asignen (de lo contrario, mostrará el valor de los segundos del offset), por lo que el mapa tendrá más de 120K entradas!

Para construir este mapa, he hecho 2 bucles:

  • El primer bucle mapea los desplazamientos de toda la hora ( +01:00 a +1 , -02:00 a -2 y así sucesivamente)
  • El segundo bucle mapea todos los otros valores (permanecen sin cambios):
    • horas enteras> = 10 (como +10:00 )
    • no-horas enteras (como +05:30 )

El código para crear el formateador:

 // builds a hashmap to map all offset values Map<Long, String> map = new HashMap<>(); // First loop: Map whole hours from 1 to 9 and from -9 to -1 // So a "+01:00" offset is displayed as "+1" for (int i = 1; i <= 9; i++) { long seconds = ZoneOffset.ofHours(i).getTotalSeconds(); // 1 hour offset maps to "+1" and so on map.put(seconds, "+" + i); // -1 hour offset maps to "-1" and so on map.put(-seconds, "-" + i); } // second loop: Need to map all other possible values for not-whole hours // offsets like "+10:00" and "+01:30" are not changed int minOffset = ZoneOffset.MIN.getTotalSeconds(); int maxOffset = ZoneOffset.MAX.getTotalSeconds(); for (long i = minOffset; i <= maxOffset; i++) { // the map already contains whole hours, don't need to overwrite the values if (!map.containsKey(i)) { // uses default String representation (like "+05:30") map.put(i, ZoneOffset.ofTotalSeconds((int) i).getId()); } } // create the formatter DateTimeFormatter formatter = new DateTimeFormatterBuilder() // year/month/day and the "|" .appendPattern("uuuu/MM/dd | ") // use the map of custom values (offset will use the values in the map) .appendText(ChronoField.OFFSET_SECONDS, map) // create formatter .toFormatter(); 

Algunas pruebas:

 LocalDateTime dt = LocalDateTime.of(2017, 5, 1, 10, 0); ZonedDateTime z = ZonedDateTime.of(dt, ZoneId.of("America/Sao_Paulo")); // UTC-03:00 System.out.println(formatter.format(z)); // 2017/05/01 | -3 // just picking some timezone in Arabia Stardard Time // (there are more than one timezone in AST: https://en.wikipedia.org/wiki/UTC%2B03:00#Arabia_Standard_Time) // I don't know in which one you are z = ZonedDateTime.of(dt, ZoneId.of("Asia/Qatar")); // UTC+03:00 System.out.println(formatter.format(z)); // 2017/05/01 | +3 // 2-digit offset z = ZonedDateTime.of(dt, ZoneId.of("Asia/Vladivostok")); // UTC+10:00 System.out.println(formatter.format(z)); // 2017/05/01 | +10:00 // not whole hour z = ZonedDateTime.of(dt, ZoneId.of("Asia/Kathmandu")); // UTC+05:45 System.out.println(formatter.format(z)); // 2017/05/01 | +05:45 

La salida es:

2017/05/01 | -3
2017/05/01 | +3
2017/05/01 | +10: 00
2017/05/01 | +05: 45


Notas:

  • No sé si tener un mapa de 120K-entradas es mejor que usar expresiones regulares (depende de usted decidir). Este enfoque crea un mapa grande, pero al menos no requiere la salida de post-procesamiento (no estoy seguro si eso es un trade-off razonable)
  • Si desea que las compensaciones de hora entera> = 10 se muestren como +10 , +11 y así sucesivamente, simplemente cambie la primera for bucle a for (int i = 1; i <= maxOffsetYouWant; i++) – recordando que el máximo valor posible para maxOffsetYouWant es 18 .

Utilice la siguiente lógica para obtener el formato de fecha deseado.

  public static void main(String[] args) { Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, 1); SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd"); System.out.println(cal.getTime()); // Output "Wed Sep 26 14:23:28 EST 2012" String formatted = format1.format(cal.getTime()); String formattedmain=formatted.replace("-","/"); System.out.println(formatted); // Output "2012-09-26" System.out.println(formattedmain); //Output :- 2017/06/06 } 
  • ¿El selector de archivos de Android 4.4 WebView no se abre?
  • Android: Fragmentos, SQLite y cargadores
  • Android: no se puede llamar a setOnItemClickListener desde un ListView
  • Gestión de sesiones de Android
  • Android SQLiteException "no such table" durante la compilación: tabla INSERT INTO
  • Android: IllegalStateException llamando a DialogFragment
  • ¿El hecho de tener activos no utilizados en la carpeta de activos afectan al tamaño de la aplicación?
  • Bytes comprimidos de la matriz Java de .NET Webservice
  • IntelliJ IDEA 12 clase duplicada R.java y BuildConfig.java
  • Parada de la conexión del proxy de medios de Android
  • ¿Es posible detectar de forma fiable en tiempo de ejecución qué tienda instaló una aplicación de Android (Google Play o Amazon Market)?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.