Solución:
Esta pregunta y las respuestas ahora están anticuadas. Usan clases de fecha y hora antiguas obsoletas por el marco java.time integrado en Java 8 y versiones posteriores. Las antiguas clases están mal diseñadas, son confusas y problemáticas; Evítales.
Evite los códigos de zona de 3-4 letras
Evite los códigos de 3-4 letras como BST
. No están estandarizados ni son únicos. En realidad, no representan zonas horarias. Y agregan aún más confusión al problema del horario de verano (DST).
En su lugar, use las zonas horarias adecuadas. La mayoría son continent/region
formato como Europe/London
.
Evite configurar la zona horaria predeterminada
Vocación java.util.TimeZone.setDefault
debe hacerse solo en los casos más extremos. Esta llamada afecta inmediatamente a todo el código que se ejecuta en todos los subprocesos de todas las aplicaciones dentro de la JVM durante tiempo de ejecución.
En su lugar, en todo su código de fecha y hora, especifique la zona horaria deseada / esperada. Si se omite, Java retrocede confiando implícitamente en la zona horaria predeterminada actual de la JVM. Como se señaló anteriormente, este valor predeterminado puede cambiar en cualquier momento durante el tiempo de ejecución. En su lugar, especifique explícitamente. Si especifica su zona horaria deseada / esperada como un argumento pasado de forma rutinaria, la zona horaria predeterminada actual es discutible, irrelevante.
java.time
El marco java.time está integrado en Java 8 y versiones posteriores. Ver tutorial. Definido por JSR 310. Inspirado en la exitosa biblioteca Joda-Time.
Instant
Un Instant
es un momento en la línea de tiempo en UTC.
El siguiente ejemplo muestra cómo las clases java.time pueden analizar / generar cadenas de forma predeterminada si están en formato estándar ISO 8601, sin necesidad de especificar un patrón de análisis. Usar DateTimeFormatter
class para especificar otros patrones no estándar.
Instant instant = Instant.parse( "2011-12-27T09:00:00Z" );
ZonedDateTime
Aplique una zona horaria según sea necesario, produciendo un ZonedDateTime
.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );
Generando cadenas
Puede producir representaciones textuales del objeto ZonedDateTime utilizando un DateTimeFormatter
. Puede especificar patrones personalizados. O, como recomiendo, deje que java.time se localice por usted.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM );
Es mejor especificar el deseado / esperado Locale
por la misma razón que la zona horaria … el valor predeterminado actual de la JVM se puede cambiar en cualquier momento mediante cualquier código en cualquier hilo de cualquier aplicación que se ejecute dentro de la JVM. los Locale
determina (a) el lenguaje humano utilizado para los nombres de día y mes, y (b) las normas culturales como las comas frente a los puntos y el orden de las partes como el mes, el día o el año que vienen primero.
formatter = formatter.withLocale( Locale.CANADA_FRENCH );
String output = zdt.format( formatter );
Sobre java.time
los java.time framework está integrado en Java 8 y versiones posteriores. Estas clases suplantan a las antiguas y problemáticas clases de fecha y hora heredadas, como java.util.Date
, Calendar
Y SimpleDateFormat
.
los Joda-Time proyecto, ahora en modo de mantenimiento, aconseja la migración a las clases java.time.
Para obtener más información, consulte el Tutorial de Oracle. Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310.
Puedes intercambiar java.time objetos directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. Sin necesidad de cuerdas, sin necesidad de java.sql.*
clases.
¿Dónde obtener las clases java.time?
-
Java SE 8, Java SE 9, Java SE 10, Java SE 11y posterior: parte de la API estándar de Java con una implementación integrada.
- Java 9 agrega algunas funciones y correcciones menores.
-
Java SE 6 y Java SE 7
- La mayor parte de la funcionalidad de java.time está retroportada a Java 6 y 7 en ThreeTen-Backport.
-
Androide
- Versiones posteriores de implementaciones de paquetes de Android del java.time clases.
- Para Android anterior (<26), el ThreeTenABP el proyecto se adapta ThreeTen-Backport (mencionado anteriormente). Ver Cómo usar ThreeTenABP….
los ThreeTen-Extra el proyecto extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval
, YearWeek
, YearQuarter
, y más.
Creo que está utilizando el patrón correcto para sus requisitos, sin embargo, el JDK no conoce el nombre de su zona horaria, por lo que cambia a usar un valor de compensación GMT en su lugar.
Cuando formateo una fecha usando su patrón, obtengo “GMT” para la parte de la zona horaria.
Que hace TimeZone.getDefault().getDisplayName()
¿darte? Para mí, obtengo “Greenwich Mean Time”.
No es una solución elegante en absoluto, pero funciona para nosotros. Tuve que crear una implementación personalizada para DateFormat / SimpleDateFormat. Esto se parece a lo siguiente:
static {
// this would be initialized like something as follows when the application starts
// which causes the headaches of SimpleDateFormat not to work...
SimpleTimeZone tz = new SimpleTimeZone(0, "Out Timezone");
TimeZone.setDefault(tz);
}
// therefore this class will workaround the issue,
public class OurOwnCustomDateFormat
extends SimpleDateFormat {
/** The pattern to use as the format string. */
protected String pattern;
public OurOwnCustomDateFormat(String pattern) {
super(pattern);
// store the pattern
this.pattern = pattern;
}
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) {
// custom implementation to format the date and time based on our TimeZone
toAppendTo.insert(pos.getBeginIndex(), "the date with our custom format calculated here");
return toAppendTo;
}