Quiero convertir esta marca de tiempo GMT a GMT + 13:
2011-10-06 03:35:05
He probado alrededor de 100 combinaciones diferentes de DateFormat, TimeZone, Date, GregorianCalendar, etc. para intentar hacer esta tarea MUY básica.
Este código hace lo que quiero para la HORA ACTUAL:
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));
String newZealandTime = formatter.format(calendar.getTime());
Pero lo que quiero es establecer la hora en lugar de usar la hora actual.
Descubrí que cada vez que trato de establecer la hora de esta manera:
calendar.setTime(new Date(1317816735000L));
se utiliza la zona horaria de la máquina local. ¿Porqué es eso? Sé que cuando "nueva fecha ()" devuelve la hora UTC + 0, entonces, ¿por qué cuando establece la hora en milisegundos, ya no asume que la hora está en UTC?
Es posible que:
- Establecer la hora en un objeto (Calendario / Fecha / Marca de hora)
- (Posiblemente) Establezca la zona horaria de la marca de tiempo inicial (calendar.setTimeZone (...))
- Formatee la marca de tiempo con una nueva zona horaria (formatter.setTimeZone (...)))
- Devuelve una cadena con la nueva zona horaria. (formatter.format (calendar.getTime ()))
Gracias de antemano por cualquier ayuda: D
1317816735000L
la marca de tiempo es incorrecta2011-10-06 03:35:05 GMT
. De lo contrario, su enfoque es correcto.java.util.Date
,java.util.Calendar
yjava.text.SimpleDateFormat
ahora son heredadas , suplantadas por las clases java.time integradas en Java 8 y versiones posteriores. Consulte el tutorial de Oracle .Respuestas:
Para mí, la forma más sencilla de hacerlo es:
Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //Here you say to java the initial timezone. This is the secret sdf.setTimeZone(TimeZone.getTimeZone("UTC")); //Will print in UTC System.out.println(sdf.format(calendar.getTime())); //Here you set to your timezone sdf.setTimeZone(TimeZone.getDefault()); //Will print on your default Timezone System.out.println(sdf.format(calendar.getTime()));
fuente
review
líneadate = sdf.parse(review);
sdf.parse(DateObject)
no está definido en Java que estoy usandoJDK.1.7
.Comprender cómo funciona el tiempo en la computadora es muy importante. Dicho esto, estoy de acuerdo en que si se crea una API para ayudarlo a procesar el tiempo de la computadora como en tiempo real, entonces debería funcionar de tal manera que le permita tratarlo como en tiempo real. En su mayor parte, este es el caso, pero hay algunos descuidos importantes que necesitan atención.
De todos modos estoy divagando !! Si tiene su compensación UTC (es mejor trabajar en UTC que en las compensaciones GMT), puede calcular el tiempo en milisegundos y agregarlo a su marca de tiempo. Tenga en cuenta que una marca de tiempo de SQL puede variar de una marca de tiempo de Java, ya que la forma en que se calcula el tiempo transcurrido desde la época no siempre es la misma, depende de las tecnologías de base de datos y también de los sistemas operativos.
Le aconsejaría que use System.currentTimeMillis () como sus marcas de tiempo, ya que se pueden procesar de manera más consistente en Java sin preocuparse por convertir las marcas de tiempo SQL en objetos de fecha de Java, etc.
Para calcular su compensación, puede intentar algo como esto:
Long gmtTime =1317951113613L; // 2.32pm NZDT Long timezoneAlteredTime = 0L; if (offset != 0L) { int multiplier = (offset*60)*(60*1000); timezoneAlteredTime = gmtTime + multiplier; } else { timezoneAlteredTime = gmtTime; } Calendar calendar = new GregorianCalendar(); calendar.setTimeInMillis(timezoneAlteredTime); DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z"); formatter.setCalendar(calendar); formatter.setTimeZone(TimeZone.getTimeZone(timeZone)); String newZealandTime = formatter.format(calendar.getTime());
¡Espero que esto sea útil!
fuente
Como siempre, recomiendo leer este artículo sobre fecha y hora en Java para que lo entienda.
La idea básica es que 'bajo el capó' todo se hace en milisegundos UTC desde la época. Esto significa que es más fácil si opera sin usar zonas horarias en absoluto, con la excepción del formato de cadena para el usuario.
Por lo tanto, omitiría la mayoría de los pasos que ha sugerido.
Alternativamente, puede usar Joda time . He oído que es una API de fecha y hora mucho más intuitiva.
fuente
tl; dr
Instant.ofEpochMilli( 1_317_816_735_000L ) .atZone( ZoneId.of( "Pacific/Auckland" ) ) .format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( new Locale( "en" , "NZ" ) ) )
…además…
LocalDateTime.parse( "2011-10-06 03:35:05".replace( " " , "T" ) ) .atZone( ZoneId.of( "Pacific/Auckland" ) )
java.time
La Pregunta y la mayoría de las Respuestas utilizan clases de fecha y hora obsoletas de las primeras versiones de Java. Estas viejas clases han demostrado ser problemáticas y confusas. Evítales. En su lugar, use las clases java.time.
ISO 8601
Su cadena de entrada tiene casi el formato estándar ISO 8601. Simplemente reemplace el ESPACIO en el medio con un
T
.String input = "2011-10-06 03:35:05".replace( " " , "T" );
LocalDateTime
Ahora analice como a
LocalDateTime
porque la entrada carece de información sobre el desplazamiento desde UTC o la zona horaria. ALocalDateTime
no tiene concepto de desplazamiento ni de zona horaria, por lo que no representa un momento real en la línea de tiempo.ZoneOffset
Parece estar diciendo que, desde el contexto empresarial, sabe que la intención de esta cadena es representar un momento 13 horas antes de UTC. Así que instanciamos a
ZoneOffset
.ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe.
OffsetDateTime
Aplicarlo para obtener un
OffsetDateTime
objeto. Este se convierte en un momento real en la línea de tiempo.ZoneId
Pero luego mencionas Nueva Zelanda. Así que tenías en mente una zona horaria específica. Una zona horaria es un desfase de UTC más un conjunto de reglas para manejar anomalías como el horario de verano (DST). Por tanto, podemos especificar un
ZoneId
a un enZonedDateTime
lugar de un simple desplazamiento.Especifique un nombre de zona horaria adecuado . Nunca use la abreviatura de 3-4 letras como
EST
oIST
ya que no son zonas horarias verdaderas, no están estandarizadas y ni siquiera son únicas (!). Por ejemploPacific/Auckland
,.ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime
Aplicar el
ZoneId
.Puede ajustarse fácilmente a otra zona para el mismo momento en la línea de tiempo.
ZoneId zParis = ZoneId.of( "Europe/Paris" ); ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis ); // Same moment in time, but seen through lens of Paris wall-clock time.
Contar desde la época
Recomiendo encarecidamente no manejar los valores de fecha y hora como un recuento de la época, como milisegundos desde el comienzo de 1970 UTC. Pero si es necesario, cree un a
Instant
partir de ese número.Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L );
Luego asigne una zona horaria como se ve arriba, si lo desea, para alejarse de UTC.
ZoneId z = ZoneId.of( "Pacific/Auckland" ); ZonedDateTime zdt = instant.atZone( z );
Tu valor de
1_317_816_735_000L
es:2011-10-05T12:12:15Z
(Mié, 05 de Octubre de 2011 12:12:15 GMT)2011-10-06T01:12:15+13:00[Pacific/Auckland]
(Jueves 06 de octubre de 2011 01:12:15 en Auckland Nueva Zelanda).Generar cadenas
Para generar una cadena en formato estándar ISO 8601 , simplemente llame
toString
. Tenga en cuenta queZonedDateTime
prudentemente amplía el formato estándar agregando el nombre de la zona horaria entre corchetes.Para otros formatos, busque Stack Overflow para la
DateTimeFormatter
clase. Ya cubierto muchas veces.Especifique ay
FormatStyle
aLocale
.Locale l = new Locale( "en" , "NZ" ); DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l ); String output = zdt.format( f );
Tenga en cuenta que la zona horaria no tiene nada que ver con la configuración regional. Puede hacer que
Europe/Paris
se muestre una fecha y hora en el idioma japonés y las normas culturales, o unaAsia/Kolkata
fecha y hora en el idioma portugués y las normas culturales de Brasil.Acerca de java.time
El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases sustituyen a las clases de fecha y hora viejas problemáticas tales como
java.util.Date
,.Calendar
, yjava.text.SimpleDateFormat
.El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a java.time.
Para obtener más información, consulte el tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones.
Gran parte de la funcionalidad de java.time se ha actualizado a Java 6 y 7 en ThreeTen-Backport y se ha adaptado aún más a Android en ThreeTenABP (consulte Cómo utilizar… ).
El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Usted puede encontrar algunas clases útiles aquí, como
Interval
,YearWeek
,YearQuarter
, y mucho más.fuente
La solución es bastante simple (Java puro, simple):
System.out.println(" NZ Local Time: 2011-10-06 03:35:05"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime localNZ = LocalDateTime.parse("2011-10-06 03:35:05",formatter); ZonedDateTime zonedNZ = ZonedDateTime.of(localNZ,ZoneId.of("+13:00")); LocalDateTime localUTC = zonedNZ.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); System.out.println("UTC Local Time: "+localUTC.format(formatter));
LA SALIDA ES:
NZ Local Time: 2011-10-06 03:35:05 UTC Local Time: 2011-10-05 14:35:05
fuente
Eché un vistazo y no creo que haya una zona horaria en Java que sea GMT + 13. Así que creo que debes usar:
Calendar calendar = Calendar.getInstance(); //OR Calendar.getInstance(TimeZone.getTimeZone("GMT")); calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY)+13); Date d = calendar.getTime();
(Si lo hay, cambie "GMT" a esa zona horaria y elimine la segunda línea de código)
O
SimpleDateFormat df = new SimpleDateFormat(); df.setTimeZone(TimeZone.getTimeZone("GMT+13")); System.out.println(df.format(c.getTime()));
Si desea establecer una fecha / hora específica, también puede usar:
calendar.set(Calendar.DATE, 15); calendar.set(Calendar.MONTH, 3); calendar.set(Calendar.YEAR, 2011); calendar.set(Calendar.HOUR_OF_DAY, 13); calendar.set(Calendar.MINUTE, 45); calendar.set(Calendar.SECOND, 00);
fuente
Podemos manejar esto usando el valor de compensación
public static long convertDateTimeZone(long lngDate, String fromTimeZone, String toTimeZone){ TimeZone toTZ = TimeZone.getTimeZone(toTimeZone); Calendar toCal = Calendar.getInstance(toTZ); TimeZone fromTZ = TimeZone.getTimeZone(fromTimeZone); Calendar fromCal = Calendar.getInstance(fromTZ); fromCal.setTimeInMillis(lngDate); toCal.setTimeInMillis(fromCal.getTimeInMillis() + toTZ.getOffset(fromCal.getTimeInMillis()) - TimeZone.getDefault().getOffset(fromCal.getTimeInMillis())); return toCal.getTimeInMillis(); }
Fragmento de código de prueba:
System.out.println(new Date().getTime()) System.out.println(convertDateTimeZone(new Date().getTime(), TimeZone .getDefault().getID(), "EST"));
Salida: 1387353270742 1387335270742
fuente
He probado este código
try{ SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss Z"); Date datetime = new Date(); System.out.println("date "+sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); System.out.println("GMT "+ sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("GMT+13")); System.out.println("GMT+13 "+ sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); System.out.println("utc "+sdf.format(datetime)); Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT")); DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z"); formatter.setTimeZone(TimeZone.getTimeZone("GMT+13")); String newZealandTime = formatter.format(calendar.getTime()); System.out.println("using calendar "+newZealandTime); }catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
y obteniendo este resultado
date 06-10-2011 10:40:05 +0530 GMT 06-10-2011 05:10:05 +0000 // here getting 5:10:05 GMT+13 06-10-2011 06:10:05 +1300 // here getting 6:10:05 utc 06-10-2011 05:10:05 +0000 using calendar 06 Oct 2011 18:10:05 GMT+13:00
fuente
Joda-Time
Las clases java.util.Date/Calendar son un desastre y deben evitarse.
Actualización: el proyecto Joda-Time está en modo de mantenimiento. El equipo aconseja la migración a las clases java.time.
Aquí está su respuesta usando la biblioteca Joda-Time 2.3. Muy fácil.
Como se indica en el código de ejemplo, le sugiero que utilice zonas horarias con nombre siempre que sea posible para que su programación pueda manejar el horario de verano (DST) y otras anomalías.
Si hubiera colocado un
T
en el medio de su cadena en lugar de un espacio, podría omitir las dos primeras líneas de código, tratando con un formateador para analizar la cadena. El constructor DateTime puede tomar una cadena en formato ISO 8601 .// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so. // import org.joda.time.*; // import org.joda.time.format.*; // Parse string as a date-time in UTC (no time zone offset). DateTimeFormatter formatter = org.joda.time.format.DateTimeFormat.forPattern( "yyyy-MM-dd' 'HH:mm:ss" ); DateTime dateTimeInUTC = formatter.withZoneUTC().parseDateTime( "2011-10-06 03:35:05" ); // Adjust for 13 hour offset from UTC/GMT. DateTimeZone offsetThirteen = DateTimeZone.forOffsetHours( 13 ); DateTime thirteenDateTime = dateTimeInUTC.toDateTime( offsetThirteen ); // Hard-coded offsets should be avoided. Better to use a desired time zone for handling Daylight Saving Time (DST) and other anomalies. // Time Zone list… http://joda-time.sourceforge.net/timezones.html DateTimeZone timeZoneTongatapu = DateTimeZone.forID( "Pacific/Tongatapu" ); DateTime tongatapuDateTime = dateTimeInUTC.toDateTime( timeZoneTongatapu );
Elimina esos valores ...
System.out.println( "dateTimeInUTC: " + dateTimeInUTC ); System.out.println( "thirteenDateTime: " + thirteenDateTime ); System.out.println( "tongatapuDateTime: " + tongatapuDateTime );
Cuando se ejecuta ...
fuente
mostrar fecha y hora para todas las zonas horarias
import java.util.Calendar; import java.util.TimeZone; import java.text.DateFormat; import java.text.SimpleDateFormat; static final String ISO8601 = "yyyy-MM-dd'T'HH:mm:ssZ"; DateFormat dateFormat = new SimpleDateFormat(ISO8601); Calendar c = Calendar.getInstance(); String formattedTime; for (String availableID : TimeZone.getAvailableIDs()) { dateFormat.setTimeZone(TimeZone.getTimeZone(availableID)); formattedTime = dateFormat.format(c.getTime()); System.out.println(formattedTime + " " + availableID); }
fuente
Podemos obtener la marca de tiempo UTC / GMT de la fecha indicada.
/** * Get the time stamp in GMT/UTC by passing the valid time (dd-MM-yyyy HH:mm:ss) */ public static long getGMTTimeStampFromDate(String datetime) { long timeStamp = 0; Date localTime = new Date(); String format = "dd-MM-yyyy HH:mm:ss"; SimpleDateFormat sdfLocalFormat = new SimpleDateFormat(format); sdfLocalFormat.setTimeZone(TimeZone.getDefault()); try { localTime = (Date) sdfLocalFormat.parse(datetime); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.getDefault()); TimeZone tz = cal.getTimeZone(); cal.setTime(localTime); timeStamp = (localTime.getTime()/1000); Log.d("GMT TimeStamp: ", " Date TimegmtTime: " + datetime + ", GMT TimeStamp : " + localTime.getTime()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return timeStamp; }
Devolverá la hora UTC según la fecha pasada.
Podemos revertir como la marca de tiempo UTC a la fecha y hora actuales (viceversa)
public static String getLocalTimeFromGMT(long gmtTimeStamp) { try{ Calendar calendar = Calendar.getInstance(); TimeZone tz = TimeZone.getDefault(); calendar.setTimeInMillis(gmtTimeStamp * 1000); // calendar.add(Calendar.MILLISECOND, tz.getOffset(calendar.getTimeInMillis())); SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); Date currenTimeZone = (Date) calendar.getTime(); return sdf.format(currenTimeZone); }catch (Exception e) { } return ""; }
Espero que esto ayude a otros. ¡¡Gracias!!
fuente
Una forma rápida es:
String dateText ="Thu, 02 Jul 2015 21:51:46"; long hours = -5; // time difference between places DateTimeFormatter formatter = DateTimeFormatter.ofPattern(E, dd MMM yyyy HH:mm:ss, Locale.ENGLISH); LocalDateTime date = LocalDateTime.parse(dateText, formatter); date = date.with(date.plusHours(hours)); System.out.println("NEW DATE: "+date);
Salida
NUEVA FECHA: 2015-07-02T16: 51: 46
fuente
Su enfoque funciona sin ninguna modificación.
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); // Timestamp for 2011-10-06 03:35:05 GMT calendar.setTime(new Date(1317872105000L)); DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); formatter.setTimeZone(TimeZone.getTimeZone("GMT+13")); // Prints 2011-10-06 16:35:05 GMT+13:00 System.out.println(formatter.format(calendar.getTime()));
fuente
public Timestamp convertLocalTimeToServerDatetime(String dt,String timezone){ String clientDnT = dt ;// "2017-06-01 07:20:00"; try{ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = sdf.parse(clientDnT); TimeZone tz = TimeZone.getTimeZone(timezone.trim()); // get time zone of user sdf.setTimeZone(tz); // Convert to servertime zone SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); TimeZone tzInAmerica = TimeZone.getDefault(); sdf1.setTimeZone(tzInAmerica); // assign date to date String serverDate = sdf1.format(date); // Convert to servertime zone to Timestamp Date date2 = sdf.parse(serverDate); Timestamp tsm = new Timestamp(date2.getTime()); return tsm; } catch(Exception e){ System.err.println(e); } return null; }
fuente
var _timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
y en JavaTimeZone tz = TimeZone.getDefault(); tz.getID()
Para encontrar la duración o el intervalo de tiempo con dos zonas horarias diferentes
import org.joda.time.{DateTime, Period, PeriodType} val s1 = "2019-06-13T05:50:00-07:00" val s2 = "2019-10-09T11:30:00+09:00" val period = new Period(DateTime.parse(s1), DateTime.parse(s2), PeriodType dayTime()) period.getDays period.getMinutes period.getHours
período de salida = P117DT13H40M
days = 117 minutes = 40 hours = 13
fuente
Me gustaría dar la respuesta moderna.
Realmente no debería querer convertir una fecha y hora de una cadena en un desplazamiento GMT a una cadena en un desplazamiento GMT diferente y con un formato diferente. Más bien, en su programa, mantenga un instante (un punto en el tiempo) como un objeto de fecha y hora adecuado. Solo cuando necesite dar una salida de cadena, formatee su objeto en la cadena deseada.
java.time
Analizando la entrada
DateTimeFormatter formatter = new DateTimeFormatterBuilder() .append(DateTimeFormatter.ISO_LOCAL_DATE) .appendLiteral(' ') .append(DateTimeFormatter.ISO_LOCAL_TIME) .toFormatter(); String dateTimeString = "2011-10-06 03:35:05"; Instant instant = LocalDateTime.parse(dateTimeString, formatter) .atOffset(ZoneOffset.UTC) .toInstant();
Para la mayoría de los propósitos,
Instant
es una buena opción para almacenar un punto en el tiempo. Si necesita dejar explícito que la fecha y la hora provienen de GMT, use unOffsetDateTime
.Conversión, formato e impresión de resultados
ZoneId desiredZone = ZoneId.of("Pacific/Auckland"); Locale desiredeLocale = Locale.forLanguageTag("en-NZ"); DateTimeFormatter desiredFormatter = DateTimeFormatter.ofPattern( "dd MMM uuuu HH:mm:ss OOOO", desiredeLocale); ZonedDateTime desiredDateTime = instant.atZone(desiredZone); String result = desiredDateTime.format(desiredFormatter); System.out.println(result);
Este impreso:
Especifiqué la zona horaria Pacífico / Auckland en lugar de la compensación que mencionaste, +13: 00. Entendí que querías la hora de Nueva Zelanda, y Pacific / Auckland mejor le dice esto al lector. La zona horaria también tiene en cuenta el horario de verano (DST), por lo que no es necesario que lo tenga en cuenta en su propio código (para la mayoría de los propósitos).
Dado que
Oct
está en inglés, es una buena idea darle al formateador una configuración regional explícita.GMT
también puede estar localizado, pero creo que solo se imprimeGMT
en todas las configuraciones regionales.OOOO
en la cadena de patrones de formato es una forma de imprimir el desplazamiento, lo que puede ser una mejor idea que imprimir la abreviatura de la zona horaria que obtendría,z
ya que las abreviaturas de la zona horaria son a menudo ambiguas. Si lo deseaNZDT
(para el horario de verano de Nueva Zelanda), colóqueloz
allí.Tus preguntas
Responderé a sus preguntas numeradas en relación con las clases modernas en java.time.
No, las clases modernas son inmutables. Debe crear un objeto que tenga la fecha y hora deseadas desde el principio (esto tiene una serie de ventajas, incluida la seguridad de subprocesos).
El
atZone
método que utilizo en el código devuelve unZonedDateTime
con la zona horaria especificada. Otras clases de fecha y hora tienen un método similar, a veces llamadoatZoneSameInstant
o con otros nombres.Con java.time, la conversión a una nueva zona horaria y el formateo son dos pasos distintos, como se muestra.
Sí, convierta a la zona horaria deseada como se muestra y formatee como se muestra.
No es la forma en que piensas, lo que sirve para mostrar solo un par de los (muchos) problemas de diseño con las clases antiguas.
Date
no tiene zona horaria. Solo cuando lo imprime, sutoString
método toma su zona horaria local y lo usa para representar la cadena. Esto también es cierto paranew Date()
. Este comportamiento ha confundido a muchos, muchos programadores durante los últimos 25 años.Calender
tiene una zona horaria. No cambia cuando lo hacescalendar.setTime(new Date(1317816735000L));
.Enlace
Tutorial de Oracle: Fecha y hora que explica cómo usar java.time.
fuente