Moja aplikacja na Androida (w javie, w Android Studio) używa klasy „Kalendarz”. Po

Calendar cal=Calendar.getInstance();
cal.setTimeInMillis(0);
Log.i("Interim",cal.getTime().toString());

Takie wyjście daje: I/Interim: Thu Jan 01 03:00:00 GMT+02:00 1970. Moja strefa czasowa to GMT + 02:00 (Kijów, Ukraina), czas letni w styczniu nie jest stosowany. Dlaczego czas w kalendarzu jest ustawiony na 03:00? Spodziewam się 00:00 (nie biorąc pod uwagę strefy czasowej) lub 02:00 (biorąc strefę czasową), ale dlaczego 03:00?

Z góry dziękuję za każdy pomysł

PS Aby wyjaśnić okoliczności, ustawiłem strefę czasową Calendar na GMT i otrzymuję wartość godziny:

Calendar cal=Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTimeInMillis(0);
Log.i("Interim hours",Integer.toString(cal[i].get(Calendar.HOUR)));
Log.i("Interim",cal.getTime().toString());

Wbrew oczekiwaniom wynik to:

I / Interim hours: 0

I / Tymczasowe: Czw 01 Sty 03:00:00 GMT + 02:00 1970

Zatem wartość pola godziny to 0, ale czas to 03:00. Właśnie usłyszałem o 1-godzinnej zmianie 13.06.1975 (patrz odpowiedź poniżej), ale wydaje się, że dotyczy to tylko Wietnamskiej TZ, prawda?

0
Spectorsky 20 marzec 2020, 11:56

2 odpowiedzi

Najlepsza odpowiedź

Rozróżnij strefę czasową i przesunięcie . Twoja strefa czasowa to Europa / Kijów (nazwy miejsc w identyfikatorach stref czasowych są zapisywane w języku angielskim, jeśli istnieje pisownia angielska). Europa / Kijów jest na przesunięciu +02: 00 tutaj w styczniu. Było na przesunięciu +03: 00 do 27 października i ponownie będzie od 29 marca ze względu na czas letni (czas letni, czas letni). I co może niektórych zdziwić, był na offsecie +03: 00 na stałe od 1944 do 1980 roku. Tak więc w epoce - 1 stycznia 1970 00:00 UTC - czas na Ukrainie wynosił 3:00. Więc dla Ukrainy ta część twojego wyniku jest poprawna.

W skrócie: strefa czasowa obejmuje historyczne, obecne i znane przyszłe przesunięcia od UTC / GMT stosowane w tej strefie czasowej. GMT + 02: 00 to przesunięcie, a nie strefa czasowa.

Java.time i ThreeTenABP

Oto nowoczesny sposób na uzyskanie tego, o czym myślę, że chciałeś:

    ZonedDateTime epochInUkraine = Instant.EPOCH.atZone(ZoneId.of("Europe/Kiev"));
    System.out.println(epochInUkraine);

Dane wyjściowe z tych linii to:

1970-01-01T03: 00 + 03: 00 [Europa / Kijów]

Jeśli chcesz wydruk podobny do tego, który otrzymałeś podczas drukowania staromodnego obiektu java.util.Date:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            "EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
    System.out.println(epochInUkraine.format(formatter));

Czw 01 stycznia 03:00:00 EET 1970

Prawdopodobnie możesz jednak znaleźć format wyjściowy, który jeszcze lepiej pasuje do twoich odbiorców. Zostawiam tę część sobie.

Co poszło nie tak?

Dlaczego Calendar.setTimeInMillis(0) ustawia nieprawidłowy czas?

To nie. Klasa Calendar i jej podklasy są źle zaprojektowane i dawno przestarzałe, ale setTimeInMillis(0) ustawia prawidłowy czas. Zauważyłeś również, że kiedy Calendar jest w UTC, jego godzina zegarowa rano lub po południu (od 0 do 11) wynosi 0. Jak otrzymałeś wynik 03:00:00 GMT+02:00 z sprzecznością między 03:00 i +02: 00? Możliwe wyjaśnienia obejmują:

  • Najprawdopodobniej błąd po twojej stronie. Albo to nie pochodzi z Calendar, które ustawiłeś na 0, albo podczas pisania pytania skopiowałeś dane wyjściowe niedokładnie. Jeśli jeszcze raz sprawdzisz, czy potrafisz odtworzyć ten wynik, byłbym zaciekawiony.
  • Mniej prawdopodobny jest błąd w Date.toString(), który jest wywoływany niejawnie, gdy drukujesz Date otrzymany z cal.getTime().
  • Jeszcze mniej prawdopodobne, że błąd w Calendar.getTime() daje ci zły obiekt Date z Calendar.

Pytanie: Czy java.time nie wymaga interfejsu API Androida na poziomie 26?

Java.time działa dobrze zarówno na starszych, jak i nowszych urządzeniach z Androidem. Wymaga tylko co najmniej Javy 6 .

  • W Javie 8 i późniejszych oraz na nowszych urządzeniach z Androidem (od poziomu API 26) wbudowane jest nowoczesne API.
  • W wersjach Java 6 i 7 innych niż Android pobierz ThreeTen Backport, zaplecze nowoczesnych klas (ThreeTen dla JSR 310; patrz linki na dole).
  • Na (starszym) systemie Android użyj wersji ThreeTen Backport na Androida. Nazywa się ThreeTenABP. I pamiętaj, aby zaimportować klasy daty i godziny z org.threeten.bp z podpakietami.

Spinki do mankietów

2
Ole V.V. 21 marzec 2020, 05:31

Jeśli dane wprowadzono przed 13/06/1975, wynik zawsze wynosi +1 godzina. Ten dzień ma 25 godzin. Możesz to sprawdzić https://currentmillis.com/. Jeśli na wejściu 13/06/1975 otrzymaliśmy 171824400000, a 12/06/1975 otrzymaliśmy 171734400000.

171824400000 - 171734400000 = 90000000.

90000000 / (60 * 60 * 1000) = 25 (???)

Więc myślę, że możesz dodać 1 godzinę, jeśli wprowadzisz dane przed 13/06/1975

0
chau nguyen ngoc 20 marzec 2020, 09:52