Si ejecuto el siguiente programa, que analiza dos cadenas de fechas que hacen referencia a tiempos de 1 segundo de diferencia y los compara:
public static void main(String[] args) throws ParseException {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str3 = "1927-12-31 23:54:07";
String str4 = "1927-12-31 23:54:08";
Date sDt3 = sf.parse(str3);
Date sDt4 = sf.parse(str4);
long ld3 = sDt3.getTime() /1000;
long ld4 = sDt4.getTime() /1000;
System.out.println(ld4-ld3);
}
La salida es:
353
¿Por qué ld4-ld3
no 1
(como esperaría de la diferencia de un segundo en los tiempos), pero 353
?
Si cambio las fechas a las horas 1 segundo después:
String str3 = "1927-12-31 23:54:08";
String str4 = "1927-12-31 23:54:09";
Entonces ld4-ld3
será 1
.
Versión de Java:
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)
Timezone(`TimeZone.getDefault()`):
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
offset=28800000,dstSavings=0,
useDaylight=false,
transitions=19,
lastRule=null]
Locale(Locale.getDefault()): zh_CN
Es un cambio de zona horaria el 31 de diciembre en Shanghai.
Consulte esta página para obtener detalles de 1927 en Shanghai. Básicamente, a la medianoche de finales de 1927, los relojes retrocedieron 5 minutos y 52 segundos. Entonces, "1927-12-31 23:54:08" en realidad sucedió dos veces, y parece que Java lo está analizando como el último instante posible para esa fecha / hora local, de ahí la diferencia.
Solo otro episodio en el mundo a menudo extraño y maravilloso de las zonas horarias.
EDITAR: ¡ Deja de presionar! Cambios en el historial ...
La pregunta original ya no demostraría el mismo comportamiento, si se reconstruyera con la versión 2013a de TZDB . En 2013a, el resultado sería 358 segundos, con un tiempo de transición de 23:54:03 en lugar de 23:54:08.
Solo me di cuenta de esto porque estoy recopilando preguntas como esta en Noda Time, en forma de pruebas unitarias ... La prueba ahora se ha cambiado, pero simplemente muestra que ni siquiera los datos históricos son seguros.
EDITAR: La historia ha cambiado de nuevo ...
En TZDB 2014f, el tiempo del cambio se ha movido a 1900-12-31, y ahora es un cambio de solo 343 segundos (por lo que el tiempo entre t
y t+1
es 344 segundos, si ve lo que quiero decir).
EDITAR: Para responder una pregunta sobre una transición en 1900 ... parece que la implementación de la zona horaria de Java trata todas las zonas horarias simplemente como si estuvieran en su hora estándar para cualquier instante antes del inicio de las 1900 UTC:
import java.util.TimeZone;
public class Test {
public static void main(String[] args) throws Exception {
long startOf1900Utc = -2208988800000L;
for (String id : TimeZone.getAvailableIDs()) {
TimeZone zone = TimeZone.getTimeZone(id);
if (zone.getRawOffset() != zone.getOffset(startOf1900Utc - 1)) {
System.out.println(id);
}
}
}
}
El código anterior no produce salida en mi máquina con Windows. Por lo tanto, cualquier zona horaria que tenga un desplazamiento diferente al estándar a principios de 1900 lo contará como una transición. La propia TZDB tiene algunos datos que se remontan a antes, y no se basa en ninguna idea de un tiempo estándar "fijo" (que es lo que se getRawOffset
supone que es un concepto válido), por lo que otras bibliotecas no necesitan introducir esta transición artificial.
Ha encontrado una discontinuidad de la hora local :
Cuando la hora estándar local estaba a punto de llegar al domingo 1 de enero de 1928, los relojes de las 00:00:00 se retrasaron 0:05:52 horas al sábado 31 de diciembre de 1927, 23:54:08 hora estándar local.
Esto no es particularmente extraño y ha sucedido en casi todas partes en un momento u otro, ya que las zonas horarias se cambiaron o cambiaron debido a acciones políticas o administrativas.
La moraleja de esta extrañeza es:
Al incrementar el tiempo, debe volver a convertir a UTC y luego sumar o restar. Utilice la hora local solo para la visualización.
De esta manera, podrá recorrer los períodos en los que las horas o los minutos suceden dos veces.
Si convirtió a UTC, agregue cada segundo y conviértalo a la hora local para mostrarlo. Pasaría por 11:54:08 pm LMT - 11:59:59 pm LMT y luego 11:54:08 pm CST - 11:59:59 pm CST.
En lugar de convertir cada fecha, puede utilizar el siguiente código:
long difference = (sDt4.getTime() - sDt3.getTime()) / 1000;
System.out.println(difference);
Y luego mira que el resultado es:
1
Lamento decirlo, pero la discontinuidad del tiempo se ha movido un poco en
JDK 6 hace dos años, y en JDK 7 recientemente en la actualización 25 .
Lección para aprender: evite las horas que no sean UTC a toda costa, excepto quizás para la visualización.
Como explicaron otros, hay una discontinuidad de tiempo allí. Hay dos posibles desplazamientos de zona horaria para 1927-12-31 23:54:08
at Asia/Shanghai
, pero solo un desplazamiento para 1927-12-31 23:54:07
. Entonces, dependiendo de qué compensación se use, hay una diferencia de un segundo o una diferencia de 5 minutos y 53 segundos.
Este ligero cambio de compensaciones, en lugar del horario de verano habitual al que estamos acostumbrados, oscurece un poco el problema.
Tenga en cuenta que la actualización de 2013a de la base de datos de la zona horaria movió esta discontinuidad unos segundos antes, pero el efecto aún sería observable.
El nuevo java.time
paquete en Java 8 permite que el usuario vea esto con mayor claridad y proporciona herramientas para manejarlo. Dado:
DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.append(DateTimeFormatter.ISO_LOCAL_DATE);
dtfb.appendLiteral(' ');
dtfb.append(DateTimeFormatter.ISO_LOCAL_TIME);
DateTimeFormatter dtf = dtfb.toFormatter();
ZoneId shanghai = ZoneId.of("Asia/Shanghai");
String str3 = "1927-12-31 23:54:07";
String str4 = "1927-12-31 23:54:08";
ZonedDateTime zdt3 = LocalDateTime.parse(str3, dtf).atZone(shanghai);
ZonedDateTime zdt4 = LocalDateTime.parse(str4, dtf).atZone(shanghai);
Duration durationAtEarlierOffset = Duration.between(zdt3.withEarlierOffsetAtOverlap(), zdt4.withEarlierOffsetAtOverlap());
Duration durationAtLaterOffset = Duration.between(zdt3.withLaterOffsetAtOverlap(), zdt4.withLaterOffsetAtOverlap());
Luego durationAtEarlierOffset
será un segundo, mientras durationAtLaterOffset
que serán cinco minutos y 53 segundos.
Además, estas dos compensaciones son las mismas:
// Both have offsets +08:05:52
ZoneOffset zo3Earlier = zdt3.withEarlierOffsetAtOverlap().getOffset();
ZoneOffset zo3Later = zdt3.withLaterOffsetAtOverlap().getOffset();
Pero estos dos son diferentes:
// +08:05:52
ZoneOffset zo4Earlier = zdt4.withEarlierOffsetAtOverlap().getOffset();
// +08:00
ZoneOffset zo4Later = zdt4.withLaterOffsetAtOverlap().getOffset();
Se puede ver el mismo problema comparando 1927-12-31 23:59:59
con 1928-01-01 00:00:00
, sin embargo, en este caso, es la compensación temprana que produce la divergencia más tiempo, y es la fecha más temprana que tiene dos posibles desplazamientos.
Otra forma de abordar esto es comprobar si se está produciendo una transición. Podemos hacer esto así:
// Null
ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
// An overlap transition
ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
Puede verificar si la transición es una superposición donde hay más de un desplazamiento válido para esa fecha / hora o un intervalo donde esa fecha / hora no es válida para esa identificación de zona, utilizando los métodos isOverlap()
y isGap()
en zot4
.
Espero que esto ayude a las personas a manejar este tipo de problemas una vez que Java 8 esté ampliamente disponible, o para aquellos que usan Java 7 y adoptan el backport JSR 310.
IMHO
la localización omnipresente e implícita en Java es su mayor defecto de diseño. Puede estar destinado a interfaces de usuario, pero, francamente, quién realmente usa Java para interfaces de usuario hoy, excepto para algunos IDE en los que básicamente puede ignorar la localización porque los programadores no son exactamente el público objetivo para él. Puede solucionarlo (especialmente en servidores Linux) de la siguiente manera:
LC_ALL=C TZ=UTC
A los miembros de Java Community Process les recomiendo:
UTF-8/UTC
como el valor predeterminado FIJO en su lugar porque ese es simplemente el valor predeterminado hoy. No hay razón para hacer otra cosa, excepto si desea producir hilos como este.Quiero decir, vamos, ¿las variables estáticas globales no son un patrón anti-OO? Nada más son esos omnipresentes valores predeterminados dados por algunas variables de entorno rudimentarias .......
Como dijeron otros, es un cambio de hora en 1927 en Shanghai.
Fue 23:54:07
en Shanghái, en la hora estándar local, pero luego de 5 minutos y 52 segundos, pasó al día siguiente a las 00:00:00
, y luego la hora estándar local volvió a cambiar a 23:54:08
. Entonces, es por eso que la diferencia entre los dos tiempos es de 343 segundos, no de 1 segundo, como hubiera esperado.
El tiempo también puede estropearse en otros lugares como Estados Unidos. Estados Unidos tiene el horario de verano. Cuando comienza el horario de verano, el tiempo avanza 1 hora. Pero después de un tiempo, el horario de verano finaliza y retrocede 1 hora hasta la zona horaria estándar. Entonces, a veces, al comparar tiempos en los EE. UU., La diferencia es de 3600
segundos, no de 1 segundo.
Pero hay algo diferente en estos cambios de dos tiempos. El último cambia continuamente y el primero fue solo un cambio. No volvió a cambiar ni volvió a cambiar en la misma cantidad.
Es mejor usar UTC a menos que sea necesario usar una hora que no sea UTC como en la pantalla.
Esto sucede porque esas son las reglas de zona horaria para el año 31 de diciembre de 1927 en Shanghai. Si va a esta página y elige "Cambios de zona horaria de 1900 a 1924", verá que en 1900 la fecha y la hora son "UTC +8: 05: 43 horas durante todo el período".
Entonces, Java solo muestra la hora configurada para esa zona horaria, en ese año.
Si cambia su zona horaria predeterminada a Hong Kong, se mostrarán los resultados correctos.
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Hong_Kong"));
Tenga en cuenta que la zona horaria cambió de CST (hora estándar de China, el "equivalente de 3 letras" a Asia / Shanghai) a HKT (el nombre de 3 letras de la zona horaria de Hong Kong).
Pero cambiar la zona horaria no es una buena solución. Por lo tanto, utilice la hora UTC del sistema siempre que sea posible. Siempre dará la hora local después de la conversión.
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Anteriormente, Kotaku informó que un hotel Godzilla se estaba abriendo en Tokio este abril. Junto al hotel, estaba programada la aparición de una enorme cabeza de 'Zilla, pero todo lo que hemos visto fueron imágenes conceptuales computarizadas.
Foto: Getty Desde que lanzó The Boring Company hace un año, Elon Musk ha mencionado varios sitios de construcción posibles para el negocio de perforación de túneles y ha descartado una vaga referencia a una aprobación gubernamental "verbal" para un túnel Hyperloop que conecta la ciudad de Nueva York y Washington. , CC. Pero ahora sabemos que al menos un alcalde quiere que Musk perfore un agujero debajo de su ciudad.
Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.
Hemos pirateado algunas ciudades industriales en esta columna, como Los Ángeles y Las Vegas. Ahora es el momento de una ciudad militar-industrial-compleja.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.