Java: ¿cómo se convierte una marca de tiempo UTC a hora local?

Tengo una marca de tiempo que está en UTC y quiero convertirla a la hora local sin usar una llamada API como TimeZone.getTimeZone("PST") . ¿Cómo se supone que debes hacer esto? He estado usando el siguiente código sin mucho éxito:

 private static final SimpleDateFormat mSegmentStartTimeFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); Calendar calendar = Calendar.getInstance(); try { calendar.setTime(mSegmentStartTimeFormatter.parse(startTime)); } catch (ParseException e) { e.printStackTrace(); } return calendar.getTimeInMillis(); 

Valor de entrada de muestra: [2012-08-15T22:56:02.038Z]

debe devolver el equivalente de [2012-08-15T15:56:02.038Z]

Date no tiene zona horaria y se almacena internamente en UTC. Solo cuando se formatea una fecha se aplica la corrección de zona horaria. Cuando se utiliza un DateFormat , se establece de manera predeterminada en la zona horaria de la JVM en la que se está ejecutando. Utilice setTimeZone para cambiarlo según sea necesario.

 DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); utcFormat.setTimeZone(TimeZone.getTimeZone("UTC")); Date date = utcFormat.parse("2012-08-15T22:56:02.038Z"); DateFormat pstFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); pstFormat.setTimeZone(TimeZone.getTimeZone("PST")); System.out.println(pstFormat.format(date)); 

Esto imprime 2012-08-15T15:56:02.038

Tenga en cuenta que omite la 'Z' en el formato PST ya que indica UTC. Si acaba de ir con Z , la salida sería 2012-08-15T15:56:02.038-0700

Utilice la API moderna de fecha y hora de Java, y esto es sencillo:

  String inputValue = "2012-08-15T22:56:02.038Z"; Instant timestamp = Instant.parse(inputValue); ZonedDateTime losAngelesTime = timestamp.atZone(ZoneId.of("America/Los_Angeles")); System.out.println(losAngelesTime); 

Esto imprime

 2012-08-15T15:56:02.038-07:00[America/Los_Angeles] 

Puntos a tener en cuenta:

  • Hay un pequeño error en tus expectativas. La Z en su marca de tiempo significa UTC, también conocida como Zulu. Entonces, en su valor de tiempo local, Z no debería estar allí. Más bien, querría un valor de retorno como, por ejemplo, 2012-08-15T15:56:02.038-07:00 , ya que el desplazamiento ahora es de -7 horas en lugar de Z.
  • Evite las abreviaturas de tres zonas horarias. No están estandarizados y, por lo tanto, a menudo son ambiguos. PST, por ejemplo, puede significar Philppine Standard Time, Pacific Standard Time o Pitcairn Standard Time (aunque S en una abreviatura es a menudo para el horario de verano (lo que significa DST)). Si pretendía la hora estándar del Pacífico, ni siquiera es una zona horaria, ya que en verano (donde cae la indicación de fecha y hora de la muestra) se usa el horario de verano del Pacífico. En lugar de las abreviaturas, use identificadores de zona horaria en el formato región / ciudad como en mi código.
  • Las marcas de tiempo generalmente se manejan mejor como objetos Instant . Convierta a ZonedDateTime solo cuando tenga una necesidad, como para la presentación.

Pregunta: ¿Puedo usar la API moderna con mi versión de Java?

Si usa al menos Java 6 , puede hacerlo.

  • En Java 8 y versiones posteriores, la nueva API viene incorporada.
  • En Java 6 y 7 obtenemos el ThreeTen Backport , el backport de las nuevas clases (eso es ThreeTen for JSR-310, donde se definió por primera vez la API moderna).
  • En Android, use la edición de Android de ThreeTen Backport. Se llama ThreeTenABP, y creo que hay una explicación maravillosa en esta pregunta: Cómo usar ThreeTenABP en Android Project .

Aquí hay una solución simple modificada

  public String convertToCurrentTimeZone(String Date) { String converted_date = ""; try { DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); utcFormat.setTimeZone(TimeZone.getTimeZone("UTC")); Date date = utcFormat.parse(Date); DateFormat currentTFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); currentTFormat.setTimeZone(TimeZone.getTimeZone(getCurrentTimeZone())); converted_date = currentTFormat.format(date); }catch (Exception e){ e.printStackTrace();} return converted_date; } //get the current time zone public String getCurrentTimeZone(){ TimeZone tz = Calendar.getInstance().getTimeZone(); System.out.println(tz.getDisplayName()); return tz.getID(); }