wake-up-neo.net

Datum in der aktuellen Zeitzone in Java abrufen

Ich habe in den letzten Stunden im Netz gesucht, um die Datumszeit in meiner Systemzeitzone zu ermitteln.

Wenn ich calendar.getTimezone.getDefaultName verwende, wird immer GMT zurückgegeben. (Idealerweise sollte meine aktuelle Zeitzone (IST) zurückgegeben werden.). Ich versuche, diese Zeichenfolge "2014-02-14T06: 04: 00: 00" zu konvertieren, die sich in GMT in meine Zeitzone datetime ..__ kehrt immer zur selben Zeit in GMT zurück.

Ich sehe nur, dass jeder vorschlägt, Timezone zu verwenden. d.h. 

dateFormatter.setTimezone("any_arbitary_timezone");

Punkt ist meine Anwendung wird an verschiedenen geografischen Standorten verwendet. Ich kann es nicht auf eine bestimmte Zeitzone einstellen. Es sollte auf die Zeitzone des Systems eingestellt werden, damit es in der Zeitzone angezeigt werden kann, in der sich der Benutzer gerade befindet

22
Kiran Kulkarni

So erhalten Sie die ID einer TimeZone, die dem Offset Ihrer lokalen Systemuhr entspricht.

Calendar cal = Calendar.getInstance();
long milliDiff = cal.get(Calendar.ZONE_OFFSET);
// Got local offset, now loop through available timezone id(s).
String [] ids = TimeZone.getAvailableIDs();
String name = null;
for (String id : ids) {
  TimeZone tz = TimeZone.getTimeZone(id);
  if (tz.getRawOffset() == milliDiff) {
    // Found a match.
    name = id;
    break;
  }
}
System.out.println(name);
9
Elliott Frisch

tl; dr

Verwenden Sie die modernen Java.time Klassen.

ZonedDateTime.now(           // Capture the current moment in the wall-clock time used by the people of a certain region (a time zone).
    ZoneId.systemDefault()   // Get the JVM’s current default time zone. Can change at any moment during runtime. If important, confirm with the user.
)                            // Renders a `ZonedDateTime` object. To see the same moment in UTC, extract a `Instant` object by calling `ZonedDateTime::getInstant`.

Sie können den expliziten Aufruf von ZoneId.systemDefault Weglassen.

ZonedDateTime.now()          // Capture the current moment in the JVM’s current default time zone.

Analysieren Sie Ihren String als LocalDateTime und stellen Sie die gewünschte Zeitzone ein.

LocalDateTime.parse( "2014-02-14T06:04:00:00" )    // Parse a string lacking any indicator of time zone or offset-from-UTC. *Not* a specific point on the timeline.
             .atOffset( ZoneOffset.UTC )           // Apply UTC as we are certain that offset-from-UTC of zero was intended by the supplier of that input string. Returns a `OffsetDateTime` object.
             .atZoneSameInstant(                   // Adjust into another time zone. The `sameInstant` part means the same moment, different wall-clock time. 
                 ZoneId.of( "Africa/Tunis" )       // Specify the particular zone of interest to you.
             )                                     // Returns a `ZonedDateTime` object.

Vermeiden Sie Java.util.Date & .Calendar

Diese Legacy-Klassen sind bekanntermaßen problematisch. Sun/Oracle hat das Java.time -Paket in Java 8 hinzugefügt, um sie zu ersetzen. Dieses Paket wurde von Joda-Time inspiriert.

Zu den Problemen der älteren Klassen gehört dieses verwirrende Verhalten: Während in Java.util.Date keine Zeitzoneninformationen enthalten sind, wendet die Implementierung von toString beim Generieren eines Strings die aktuelle Standardzeitzone der JVM an. Es führt Sie also in die Irre, weil es eine Zeitzone zu haben scheint, in der dies nicht der Fall ist.

Java.time

Ich versuche, diese Zeichenfolge "2014-02-14T06: 04: 00: 00" zu konvertieren, ...

In Ihrer Eingabezeichenfolge fehlt ein Indikator für die Zeitzone oder den Versatz von UTC. Wir analysieren also als LocalDateTime , dem jedes Konzept von Zone/Offset fehlt.

Ein LocalDateTime stellt not einen Moment dar, ist not ein Punkt auf der Zeitachse. Das Wort "Lokal" bedeutet hier nicht einen bestimmten Ort. Es bedeutet "überhaupt keine spezifische Lokalität". Ohne den Kontext einer Zone/eines Offsets hat dies keine wirkliche Bedeutung.

LocalDateTime ldt = LocalDateTime.parse( "2014-02-14T06:04:00:00" ) ;

… Das ist in GMT…

Sie sagen, Sie sind sicher, dass der Lieferant dieser Eingabezeichenfolge UTC als Kontext bestimmt hat. Wir können einen UTC-Offset von Null oder UTC selbst anwenden, um ein OffsetDateTime -Objekt zu erhalten. Ein OffsetDateTime is Moment, ein Punkt auf der Timeline. Wir können ZoneOffset mit der Konstante für UTC angeben, ZoneOffset.UTC .

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;

… Zu meiner Zeitzone datetime

Anscheinend möchten Sie diesen Moment in eine andere Zeitzone versetzen, um die von den Menschen einer bestimmten Region verwendete Wanduhrzeit zu sehen. Wir müssen eine Zeitzone (ZoneId) anwenden, um ein ZonedDateTime zu erhalten.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = odt.atZone( z ) ;

Anstatt eine Zeitzone anzugeben, können Sie Ihre JVM nach der aktuellen Standardzeitzone fragen. Achtung: Die aktuelle Standardzeitzone der JVM kann jederzeit durch einen beliebigen Code in einem beliebigen Thread einer beliebigen App in dieser JVM geändert werden.

ZoneId z = ZoneId.systemDefault() ;
ZonedDateTime zdt = odt.atZone( z ) ;

Punkt ist, dass meine Anwendung an verschiedenen geografischen Standorten verwendet wird.

Geben Sie einfach Ihre gewünschten/erwarteten Zeitzonen explizit an. Dies ist meiner Meinung nach immer eine gute Praxis. Die Standardzeitzone liegt außerhalb Ihrer Kontrolle als Programmierer, was es unzuverlässig macht.

Geben Sie ein richtiger Zeitzonenname im Format continent/region An, z. B. America/Montreal , Africa/Casablanca oder Pacific/Auckland. Verwenden Sie niemals die Abkürzung mit 3-4 Buchstaben wie EST oder IST, da diese nicht echte Zeitzonen sind, nicht standardisiert und nicht einmalig (!) .

Ein weiterer Tipp: In UTC arbeiten, denken, speichern und austauschen. Vergessen Sie Ihre eigene Zeitzone, denn wenn Sie in Ihre Heimatzone hin und her übersetzen, werden Sie verrückt. Stellen Sie sich UTC als One True Time vor, und andere Zonen/Offsets sind nur Variationen.

Instant instant = Instant.now() ;  // Capture current moment in UTC.

ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdtAuckland = instant.atZone( zAuckland ) ;

ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" ) ;  
ZonedDateTime zdtKolkata = instant.atZone( zKolkata ) ;

ZoneId zCasablanca = ZoneId.of( "Africa/Casablanca" ) ;  
ZonedDateTime zdtCasablanca = instant.atZone( zCasablanca ) ;

Dort haben wir vier Möglichkeiten (instant, zdtAuckland, zdtKolkata, zdtCasablanca), den gleichen Moment und denselben Punkt auf der Zeitachse gleichzeitig zu betrachten.

instant.toString (): 2018-05-08T20: 55: 14.761721Z

zdtAuckland.toString (): 2018-05-09T08: 55: 14.761721 + 12: 00 [Pacific/Auckland]

zdtKolkata.toString (): 2018-05-09T02: 25: 14.761721 + 05: 30 [Asia/Kolkata]

zdtCasablanca.toString (): 2018-05-08T21: 55: 14.761721 + 01: 00 [Africa/Casablanca]

Zone vs Offset

Ein Versatz von UTC ist einfach eine Anzahl von Stunden, Minuten und Sekunden. Nicht mehr, nicht weniger. Eine beliebige Anzahl von Zeitzonen kann sich zu einem bestimmten Zeitpunkt einen bestimmten Versatz teilen.

Eine Zeitzone ist eine Geschichte vergangener, gegenwärtiger und zukünftiger Änderungen des Versatzes, der von den Menschen einer bestimmten Region verwendet wird. Zum Beispiel ist die Sommerzeit eine Praxis, bei der die Menschen einer Region (aus unerklärlichen Gründen) beschließen, ihren Versatz zweimal im Jahr zu ändern.

Eine Zeitzone ist also immer einem bloßen Versatz vorzuziehen. Mit einer Zone können wir die Zeit auf sinnvolle Weise addieren oder subtrahieren, um Änderungen im Offset in der Geschichte dieser Region zu berücksichtigen.


About Java.time

Das Java.time Framework ist in Java 8 und höher. Diese Klassen ersetzen das lästige alte Legacy Datum-Zeit-Klassen wie Java.util.Date , Calendar , & SimpleDateFormat .

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

Weitere Informationen finden Sie im Oracle Tutorial . Durchsuchen Sie 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 Zeichenketten, keine Notwendigkeit für Klassen Java.sql.*.

Woher bekommen Sie 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 mehr .


Joda-Zeit

UPDATE: Das Joda-Time-Projekt befindet sich jetzt im Wartungsmodus. Das Team empfiehlt die Migration zu den Java.time-Klassen. Fahren Sie in dieser Antwort mit dem Abschnitt Java.time fort.

Das Joda-Time-Paket bietet eine gute Unterstützung für Zeitzonen. Im Gegensatz zu Java.util.Date kennt eine Joda-Time DateTime ihre eigene zugewiesene Zeitzone. Wenn Sie keine Zeitzone angeben, wird die aktuelle Standardzeitzone der JVM implizit zugewiesen.

DateTime dateTime = DateTime.now(); // Applies JVM’s default time zone implicitly.

Ich empfehle, sich nicht implizit auf die Standardzeitzone zu verlassen. Dies führt zu Verwirrung und Fehlern bei der Arbeit mit Datum und Uhrzeit.

DateTime dateTime = DateTime.now( DateTimeZone.getDefault() ); // Explicitly using default time zone.

Bei Bedarf können Sie eine Zeitzone zuweisen.

DateTime dateTimeKolkata = DateTime.now( DateTimeZone.forID( "Asia/Kolkata" ) ); // Specify a time zone.

Für die serverseitige Arbeit empfiehlt es sich, Geschäftslogik und Datenbankspeicherung in UTC durchzuführen.

DateTime dateTimeUtc = DateTime.now( DateTimeZone.UTC ); // Assign UTC (GMT) time zone.

Sie können von der zugewiesenen Zeitzone in eine andere konvertieren, einschließlich der aktuellen Standardzeitzone der JVM.

DateTime dateTime = dateTimeUtc.withZone( DateTimeZone.getDefault() );

Unveränderlich

Aus Gründen der Thread-Sicherheit verwendet Joda-Time nveränderliche Objekte . Anstatt ein Objekt zu ändern, erstellen Methoden wie withZone eine neue Instanz basierend auf dem Original.

Parse String

Um einen String als DateTime zu analysieren, müssen Sie beachten, ob der String einen Versatz von UTC und/oder einer Zeitzone enthält. Deiner nicht. Sie müssen also eine Zeitzone angeben, nach der diese Zeichenfolge interpretiert werden soll. Wenn Sie nicht angeben, wird die aktuelle Standardzeitzone der JVM beim Parsen verwendet.

In Ihrer Frage haben Sie angegeben, dass der String eine Datums-/Uhrzeitangabe in UTC ( GMT darstellt =).

DateTime dateTimeUtc = new DateTime( "2014-02-14T06:04:00:00", DateTimeZone.UTC );

Nach dem Parsen können Sie bei Bedarf eine andere Zeitzone zuweisen. Gleicher Zeitpunkt in der Zeitleiste des Universums, zeigt jedoch eine andere Wanduhr-Zeit .

DateTime dateTimeDefaultZone = dateTimeUtc.withZone( DateTimeZone.getDefault() );

Beachten Sie also, dass dies ein zweistufiger Prozess war. Zuerst haben wir Ihren String analysiert, indem wir unser externes Wissen über die beabsichtigte Zeitzone des Strings verwendet haben, da die interne Darstellung dieser Zeitzone oder dieses Offsets fehlte. Zweitens haben wir die Zeitzone an eine andere angepasst (die JVM-Standardzone).

Wenn Ihr String einen Versatz von +00:00 Oder das übliche Z enthalten hätte, hätten wir diese beiden Schritte zu einem zusammenfassen können.

DateTime dateTimeDefaultZone = new DateTime(  "2014-02-14T06:04:00:00Z", DateTimeZone.getDefault() ); // Apply time zone adjustment *after* parsing.

Beachten Sie, dass dieser DateTime-Konstruktor wie der oben gezeigte aussieht, sich jedoch grundlegend unterscheidet. Das Zeitzonenargument dieses Benutzers wird angewendet nach Parsen, anstatt während Parsen. Hier wird das Zeitzonenargument verwendet, um die bereits analysierte DateTime anzupassen. Das Z am Ende macht einen großen Unterschied.

Quelle der Standardzeitzone

Das JVM erhält zunächst seine Standardzeitzone vom Host-Betriebssystem. Beachten Sie jedoch, dass ein Programmierer dies überschreiben kann, indem er:

Das Überschreiben wirkt sich auf alle Threads aller Apps aus, die in dieser JVM ausgeführt werden. Sie sollten also wissen, dass die Standardzeitzone der JVM normalerweise mit dem Host-Betriebssystem identisch ist, jedoch nicht unbedingt mit der Zeitzone des Host-Betriebssystems.

52
Basil Bourque

Ich glaube, was Sie suchen, ist die Bibliothek " Joda ". Es verfügt über eine bessere Funktionalität als die Kalender- oder Datumsklassen, die in der Antwort hier angegeben sind. 

Diese Funktion sollte besonders nützlich sein.

0
BCza
      private String receivedFormat = "yyyy-MM-dd'T'HH:mm:ss", expectedFormat = "dd-MM-yyyy HH:mm:ss"; //Globall variables

        //Write these three lines in your Test Class and below 2 methods

        String dateString = "2018-08-14T07:00:00:00";
        String returnString = correctDateFormat(dateString, receivedFormat, expectedFormat);
        String result = getTimeInSelectedLocale(returnString);
    Log.i("Ayaz", "Date: " +result);



     /**
         * @param receivedDate
         * @param givenFormat
         * @param expectedFormat
         * @return returns date time in expected format
         */
        public static String correctDateFormat(String receivedDate, String givenFormat, String expectedFormat) {
            if (TextUtils.isEmpty(receivedDate)) {
                return "";
            }
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(givenFormat);
            Date newDate = null;
            try {
                newDate = simpleDateFormat.parse(receivedDate);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            simpleDateFormat = new SimpleDateFormat(expectedFormat);
            receivedDate = simpleDateFormat.format(newDate);
            return receivedDate;
        }



        /**
         * @param dateString
         * @return passed string date in different locale, My Db is in IST so I an converting IST in different locale
         */
        public  String getTimeInSelectedLocale(String dateString) {
            if (TextUtils.isEmpty(dateString)) {
                return dateString;
            }
            SimpleDateFormat sdf = new SimpleDateFormat(expectedFormat);
            sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata")); //We want Indian time to change in different locale, so this line is compulsory, you can replace with your country
            Date date1 = null;
            try {
                date1 = sdf.parse(dateString);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            //below this line -> TimeZone.getTimeZone(TimeZone.getDefault().getID(), will return current locale for example for India "Asia/Kolkata" for UAE "Asia/Dubai"
            sdf.setTimeZone(TimeZone.getTimeZone(TimeZone.getDefault().getID())); //This line chooses current local in which you want time
            String localDate = sdf.format(date1);
            return localDate;
        }

//I am converting the IST time "2018-08-14T07:00:00:00"  into UAE(Duabai) "14-08-2018 05:30:00" and other countries
0
Ayaz