web-dev-qa-db-ger.com

Wie kann ich die Zeitzone eines Java.util.Date einstellen?

Ich habe einen Java.util.Date von einer String analysiert, aber es wird die lokale Zeitzone als Zeitzone des date-Objekts festgelegt.

Die Zeitzone ist nicht in der String angegeben, aus der Date analysiert wird. Ich möchte eine bestimmte Zeitzone des date-Objekts festlegen.

Wie kann ich das machen?

173
Yatendra Goel

Verwenden Sie DateFormat. Zum Beispiel,

SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = isoFormat.parse("2010-05-23T09:01:02");
267
ZZ Coder

Beachten Sie, dass Java.util.Date-Objekte selbst keine Zeitzoneninformationen enthalten. Sie können die Zeitzone für ein Date-Objekt nicht festlegen. Das einzige, was ein Date-Objekt enthält, ist eine Anzahl von Millisekunden seit der "Epoche" - 1. Januar 1970, 00:00:00 UTC.

Wie ZZ Coder zeigt, legen Sie die Zeitzone für das Objekt DateFormat fest, um anzugeben, in welcher Zeitzone Sie Datum und Uhrzeit anzeigen möchten.

150
Jesper

tl; dr

… Geparst… aus einem String… Zeitzone ist nicht angegeben… Ich möchte eine bestimmte Zeitzone festlegen

_LocalDateTime.parse( "2018-01-23T01:23:45.123456789" )  // Parse string, lacking an offset-from-UTC and lacking a time zone, as a `LocalDateTime`.
    .atZone( ZoneId.of( "Africa/Tunis" ) )              // Assign the time zone for which you are certain this date-time was intended. Instantiates a `ZonedDateTime` object.
_

Keine Zeitzone in j.u.Date

Wie in den anderen korrekten Antworten angegeben, hat ein Java.util.Date keine Zeitzone. Es repräsentiert UTC /GMT (kein Zeitzonenversatz). Sehr verwirrend, da die toString-Methode beim Generieren einer Zeichenfolgendarstellung die Standardzeitzone der JVM anwendet.

Vermeiden Sie j.u.Date

Aus diesem und vielen anderen Gründen sollten Sie die Verwendung des integrierten Java.util.Date & .Calendar & Java.text.SimpleDateFormat vermeiden. Sie sind notorisch lästig.

Verwenden Sie stattdessen das Java.time-Paket , das mit Java 8 gebündelt ist.

Java.time

Die Java.time-Klassen können einen Moment auf der Zeitachse auf drei Arten darstellen:

  • UTC (Instant)
  • Mit einem Offset (OffsetDateTime mit ZoneOffset)
  • Mit einer Zeitzone (ZonedDateTime mit ZoneId)

Instant

In Java.time ist der grundlegende Baustein Instant , ein Moment auf der Zeitachse in UTC. Verwenden Sie Instant-Objekte für einen Großteil Ihrer Geschäftslogik.

_Instant instant = Instant.now();
_

OffsetDateTime

Wenden Sie Offset-von-UTC an, um die Wanduhrzeit ​​einiger Orte anzupassen.

Wenden Sie ein ZoneOffset an, um ein OffsetDateTime zu erhalten.

_ZoneOffset zoneOffset = ZoneOffset.of( "-04:00" );
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset );
_

ZonedDateTime

Besser ist es, ein Zeitzone , einen Versatz plus die Regeln für die Behandlung von Anomalien wie Sommerzeit (DST) anzuwenden .

Wenden Sie ein ZoneId auf ein Instant an, um ein ZonedDateTime zu erhalten. Geben Sie immer ein richtiger Zeitzonenname an. Verwenden Sie niemals 3-4 Abkürzungen wie EST oder IST, die weder eindeutig noch standardisiert sind.

_ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
_

LocalDateTime

Wenn in der Eingabezeichenfolge kein Versatz- oder Zonenindikator vorhanden war, analysieren Sie diese als LocalDateTime .

Wenn Sie sich der beabsichtigten Zeitzone sicher sind, weisen Sie eine ZoneId zu, um eine ZonedDateTime zu erstellen. Siehe obiges Codebeispiel im Abschnitt tl; dr oben.

Formatierte Zeichenfolgen

Rufen Sie die Methode toString für eine dieser drei Klassen auf, um eine Zeichenfolge zu generieren, die den Datums-/Zeitwert im Standardformat ISO 8601 darstellt. Die Klasse ZonedDateTime erweitert das Standardformat, indem der Name der Zeitzone in Klammern angehängt wird.

_String outputInstant = instant.toString(); // Ex: 2011-12-03T10:15:30Z
String outputOdt = odt.toString(); // Ex: 2007-12-03T10:15:30+01:00
String outputZdt = zdt.toString(); // Ex: 2007-12-03T10:15:30+01:00[Europe/Paris]
_

Für andere Formate verwenden Sie die Klasse DateTimeFormatter . Generell ist es am besten, diese Klasse lokalisierte Formate unter Verwendung der vom Benutzer erwarteten menschlichen Sprache und kulturellen Normen generieren zu lassen. Oder Sie können ein bestimmtes Format angeben.


Über Java.time

Das Java.time Framework ist in Java 8 und höher integriert. Diese Klassen ersetzen die lästigen alten Legacy Datum-Zeit-Klassen wie Java.util.Date , Calendar , & SimpleDateFormat =.

Das Joda-Time -Projekt, das sich jetzt im Wartungsmodus befindet, rät zur Migration auf Java.time = Klassen.

Weitere Informationen finden Sie im Oracle Tutorial . Suchen Sie in Stack Overflow nach vielen Beispielen und Erklärungen. Spezifikation ist JSR 31 .

Sie können Java.time Objekte direkt mit Ihrer Datenbank austauschen. Verwenden Sie einen JDBC-Treiber , der JDBC 4.2 oder höher entspricht. Keine Notwendigkeit für Zeichenfolgen, keine Notwendigkeit für _Java.sql.*_ Klassen.

Woher bekomme ich die Java.time-Klassen?

Das Projekt ThreeTen-Extra erweitert Java.time um zusätzliche Klassen. Dieses Projekt ist ein Testfeld für mögliche zukünftige Ergänzungen von Java.time. Hier finden Sie möglicherweise einige nützliche Klassen wie Interval , YearWeek , YearQuarter und more .


Joda-Zeit

Während Joda-Time noch aktiv gewartet wird, haben uns die Macher angewiesen, so schnell wie möglich auf Java.time zu migrieren. Ich lasse diesen Abschnitt als Referenz intakt, empfehle jedoch, stattdessen den obigen Abschnitt _Java.time_ zu verwenden.

In Joda-Time kennt ein Datum-Uhrzeit-Objekt ( DateTime ) die zugewiesene Zeitzone wirklich. Dies bedeutet einen Versatz von UTC und der Regeln und des Verlaufs der Sommerzeit (DST) dieser Zeitzone und anderer solcher Anomalien.

_String input = "2014-01-02T03:04:05";
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeIndia = new DateTime( input, timeZone );
DateTime dateTimeUtcGmt = dateTimeIndia.withZone( DateTimeZone.UTC );
_

Rufen Sie die Methode toString auf, um einen String im Format ISO 8601 zu generieren.

_String output = dateTimeIndia.toString();
_

Joda-Time bietet auch umfangreiche Funktionen zum Generieren aller Arten anderer Zeichenfolgenformate.

Bei Bedarf können Sie Joda-Time DateTime in ein Java.util.Date konvertieren.

_Java.util.Date date = dateTimeIndia.toDate();
_

Durchsuchen Sie StackOverflow nach "joda date", um viele weitere, zum Teil recht detaillierte Beispiele zu finden.


Tatsächlich gibt es eine in Java.util.Date eingebettete Zeitzone , die für einige interne Funktionen verwendet wird (siehe Kommentare zu dieser Antwort). Diese interne Zeitzone ist jedoch nicht als Eigenschaft verfügbar und kann nicht festgelegt werden. Diese interne Zeitzone ist nicht diejenige, die von der Methode toString zum Generieren einer Zeichenfolgendarstellung des Datum-Zeit-Werts verwendet wird. Stattdessen wird die aktuelle Standardzeitzone der JVM sofort angewendet. Als Abkürzung sagen wir oft "j.u.Date hat keine Zeitzone". Verwirrend? Ja. Ein weiterer Grund, diese müden alten Klassen zu meiden.

73
Basil Bourque

Sie können die Zeitzone auch auf der JVM-Ebene einstellen

Date date1 = new Date();
System.out.println(date1);

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
// or pass in a command line arg: -Duser.timezone="UTC"

Date date2 = new Date();
System.out.println(date2);

ausgabe:

Thu Sep 05 10:11:12 EDT 2013
Thu Sep 05 14:11:12 UTC 2013
62
starmer

Wenn Sie nur mit Standard-JDK-Klassen arbeiten müssen, können Sie Folgendes verwenden:

/**
 * Converts the given <code>date</code> from the <code>fromTimeZone</code> to the
 * <code>toTimeZone</code>.  Since Java.util.Date has does not really store time zome
 * information, this actually converts the date to the date that it would be in the
 * other time zone.
 * @param date
 * @param fromTimeZone
 * @param toTimeZone
 * @return
 */
public static Date convertTimeZone(Date date, TimeZone fromTimeZone, TimeZone toTimeZone)
{
    long fromTimeZoneOffset = getTimeZoneUTCAndDSTOffset(date, fromTimeZone);
    long toTimeZoneOffset = getTimeZoneUTCAndDSTOffset(date, toTimeZone);

    return new Date(date.getTime() + (toTimeZoneOffset - fromTimeZoneOffset));
}

/**
 * Calculates the offset of the <code>timeZone</code> from UTC, factoring in any
 * additional offset due to the time zone being in daylight savings time as of
 * the given <code>date</code>.
 * @param date
 * @param timeZone
 * @return
 */
private static long getTimeZoneUTCAndDSTOffset(Date date, TimeZone timeZone)
{
    long timeZoneDSTOffset = 0;
    if(timeZone.inDaylightTime(date))
    {
        timeZoneDSTOffset = timeZone.getDSTSavings();
    }

    return timeZone.getRawOffset() + timeZoneDSTOffset;
}

Gutschrift geht an diese post .

6
diadyne

Java.util.Calendar ist der übliche Weg, Zeitzonen nur mit JDK-Klassen zu behandeln. Apache Commons hat einige weitere Alternativen/Hilfsprogramme, die hilfreich sein können. Edit Spongs Notiz erinnerte mich daran, dass ich wirklich gute Dinge über Joda-Time gehört habe (obwohl ich es selbst nicht verwendet habe).

6
T.J. Crowder

Dieser Code war hilfreich in einer App, an der ich gerade arbeite:

    Instant date = null;
    Date sdf = null;
    String formatTemplate = "EEE MMM dd yyyy HH:mm:ss";
    try {
        SimpleDateFormat isoFormat = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss");
        isoFormat.setTimeZone(TimeZone.getTimeZone(ZoneId.of("US/Pacific")));
        sdf = isoFormat.parse(timeAtWhichToMakeAvailable);
        date = sdf.toInstant();

    } catch (Exception e) {
        System.out.println("did not parse: " + timeAtWhichToMakeAvailable);
    }

    LOGGER.info("timeAtWhichToMakeAvailable: " + timeAtWhichToMakeAvailable);
    LOGGER.info("sdf: " + sdf);
    LOGGER.info("parsed to: " + date);
0
VikR

Konvertieren Sie das Datum in einen String und tun Sie es mit SimpleDateFormat.

    SimpleDateFormat readFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    readFormat.setTimeZone(TimeZone.getTimeZone("GMT" + timezoneOffset));
    String dateStr = readFormat.format(date);
    SimpleDateFormat writeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    Date date = writeFormat.parse(dateStr);
0
avisper

Wenn jemand dies jemals benötigt, wenn Sie eine XMLGregorianCalendar Zeitzone von UTC in Ihre aktuelle Zeitzone konvertieren müssen, müssen Sie die Zeitzone auf 0 setzen. Dann rufen Sie toGregorianCalendar() auf - sie bleibt jedoch dieselbe Zeitzone Die Date weiß, wie sie in Ihre konvertiert wird, damit Sie die Daten von dort aus abrufen können. 

XMLGregorianCalendar xmlStartTime = DatatypeFactory.newInstance()
    .newXMLGregorianCalendar(
        ((GregorianCalendar)GregorianCalendar.getInstance());
xmlStartTime.setTimezone(0);
GregorianCalendar startCalendar = xmlStartTime.toGregorianCalendar();
Date startDate = startCalendar.getTime();
XMLGregorianCalendar xmlStartTime = DatatypeFactory.newInstance()
    .newXMLGregorianCalendar(startCalendar);
xmlStartTime.setHour(startDate.getHours());
xmlStartTime.setDay(startDate.getDate());
xmlStartTime.setMinute(startDate.getMinutes());
xmlStartTime.setMonth(startDate.getMonth()+1);
xmlStartTime.setTimezone(-startDate.getTimezoneOffset());
xmlStartTime.setSecond(startDate.getSeconds());
xmlStartTime.setYear(startDate.getYear() + 1900);
System.out.println(xmlStartTime.toString());

Ergebnis:

2015-08-26T12:02:27.183Z
2015-08-26T14:02:27.183+02:00
0
EpicPandaForce