Java 8'de UTC + 0 tarihi nasıl alınır?


108

Java'da Date sınıfıyla ilgili sorunlarım var. Tarih sınıfı yerel makine tarihini döndürüyor ancak UTC-0'a ihtiyacım var.

Google'da araştırdım ve JavaScript için harika bir çözüm buldum, ancak Java için yararlı bir şey yok.

Java 8'de UTC + 0 tarihi nasıl alınır?


12
java.util.Dateasla yerel bir makine tarihi değildir. Her zaman 1970-01-01'den beri UTC + 00: 00'a göre geçen milisaniye olarak tanımlanır. Belki de yönteminin davranışı toString()sizi gerçekten yerel saat diliminde bir temsil kullanan kafanızı karıştırır.
Meno Hochschild

Soruda olası bir cevap bulunabilir: stackoverflow.com/questions/45350095/…
Priya Jain

Yanıtlar:


146

Java 8 ile şunları yazabilirsiniz:

OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);

Yorumunuzu cevaplamak için, onu bir Tarihe (eski koda bağlı olmadığınız sürece, nedenini göremiyorum) veya çağlardan beri milis olarak dönüştürebilirsiniz:

Date date = Date.from(utc.toInstant());
long epochMillis = utc.toEpochSecond() * 1000;

1
Teşekkürler. ZonedDateTime'ı Date'e veya long (ms) 'ye dönüştürmek mümkündür?
Mark

7
Bu Yanıtlayıcının kodu teknik olarak çalışsa da, tam saat dilimi yerine yalnızca UTC'den sapma ile çalıştığımızı belirtmek OffsetDateTimeyerine kullanmak daha uygun olmaz mıydı ZonedDateTime?
Basil Bourque

179

tl; dr

Instant.now()

java.time

Java'nın en eski sürümleriyle birlikte gelen zahmetli eski tarih-saat sınıflarının yerini , Java 8 ve sonraki sürümlerde yerleşik olan java.time sınıfları almıştır . Oracle Eğitimine bakın . Çok işlevsellik içinde Java 6 ve 7 geri-taşındıktan ThreeTen-backport ve ayrıca içinde Android'e uyarlanmıştır ThreeTenABP .

Instant

An , nanosaniyeye kadar çözünürlükle UTC'deInstant zaman çizelgesindeki bir anı temsil eder .

Instant instant = Instant.now();

toStringYöntemi standart birini kullanarak tarih zaman değerini temsil eden metin ile bir String nesnesi yaratır , ISO 8601 biçimleri.

String output = instant.toString();  

2016-06-27T19: 15: 25,864Z

InstantSınıf java.time bir temel yapı bloğu sınıftır. Genel olarak en iyi uygulama, UTC'de tarih-saat değerlerini izlemek, saklamak ve değiştirmek olduğu için, tarih-saati ele alırken bu sınıfınız olmalıdır.

OffsetDateTime

Ancak Instant, alternatif biçimlerde dizeler oluşturmak için biçimlendirme seçeneklerinin olmaması gibi sınırlamaları vardır. Daha fazla esneklik için, 'den' Instante dönüştürün OffsetDateTime. UTC'den uzaklık belirtin . Java.time'da bu bir ZoneOffsetnesne anlamına gelir . Burada UTC (+00) ile bağlı kalmak istiyoruz, böylece uygun sabiti kullanabiliriz ZoneOffset.UTC.

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

2016-06-27T19: 15: 25,864Z

Veya Instantdersi atlayın .

OffsetDateTime.now( ZoneOffset.UTC )

Artık OffsetDateTimeelinizde bir nesne DateTimeFormattervarken, alternatif formatlarda metin içeren String nesneleri oluşturmak için kullanabilirsiniz . Birçok kullanım örneği için Yığın Taşması'nı arayın DateTimeFormatter.

ZonedDateTime

Belirli bir zaman dilimi için duvar saati zamanını görüntülemek istediğinizde , ZoneIdbir ZonedDateTime.

Bu örnekte Montréal saat dilimini uyguluyoruz. Yaz aylarında, Yaz Saati Uygulaması (DST) saçmalığı altında , bölgenin bir ofseti vardır -04:00. Öyleyse çıktıda günün saatinin saatler 15yerine dört saat erken olduğuna dikkat edin 19. Instantve ZonedDateTimeher ikisi de, sadece iki farklı mercekten bakıldığında aynı eşzamanlı anı temsil ediyor.

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

2016-06-27T15: 15: 25.864-04: 00 [Amerika / Montreal]

Dönüştürülüyor

Eski tarih-saat sınıflarından kaçınmanız gerekirken, gerekirse eski sınıflara eklenen yeni yöntemleri kullanarak dönüştürebilirsiniz. Burada java.util.Date.from( Instant )ve kullanıyoruz java.util.Date::toInstant.

java.util.Date utilDate = java.util.Date.from( instant );

Ve diğer yöne gidiyor.

Instant instant= utilDate.toInstant();

Benzer şekilde, içine ve içinden dönüştürmek için GregorianCalendar(alt sınıfına Calendar) eklenen yeni yöntemleri arayın java.time.ZonedDateTime.

Modern java.time ve eski sürümlerdeki tarih-saat sınıflarının türlerinin tablosu.

Hakkında java.time

Java.time çerçevesi daha sonra Java 8 ve yerleşiktir. Bu sınıflar zahmetli eski yerini mirası gibi tarih-saat sınıfları java.util.Date, Calendar& SimpleDateFormat.

Daha fazla bilgi edinmek için Oracle Eğitimi'ne bakın . Ve birçok örnek ve açıklama için Stack Overflow'da arama yapın. Spesifikasyon JSR 310'dur .

Şu anda bakım modunda olan Joda-Time projesi, java.time sınıflarına geçişi önerir .

Java.time nesnelerini doğrudan veritabanınız ile değiş tokuş edebilirsiniz . JDBC 4.2 veya üstü ile uyumlu bir JDBC sürücüsü kullanın . Dizelere gerek yok, derslere gerek yok . Hibernate 5 ve JPA 2.2 java.time'ı destekler .java.sql.*

Java.time sınıflarını nereden edinebilirim?


3
DST'nin anlamsız olduğunu söylediğiniz için
minnettarım

böylece mevcut olmayan DST eğer ZonedDateTimetamam beri gerek kalmamış ZoneIdbiri için eşleştirme ZoneOffsetbiz sadece kullanabiliriz OffsetDateTime?
wilmol

1
@wilmol Hayır. Yaz Saati Uygulaması (DST), politikacıların bu bölgelerdeki saat dilimi sınırlarını ve uzaklıklarını yeniden tanımlamayı seçmelerinin birçok nedeninden yalnızca biridir. Son zamanlarda Kuzey Kore, diplomatik nedenlerle Güney Kore ile senkronize olmak için saatini yarım saat değiştirdi. Savaşta, işgalciler / işgalciler ofseti anavatanına uyacak şekilde değiştirebilirler. Şu anda hükümetlerin DST değişikliklerini durdurmayı seçtiği ancak önceki standart saatlerine dönmek yerine kalıcı olarak DST'de kaldıkları yeni bir heves var . Her zaman her bölge değişikliğinin ofsetini planlayın, aksi takdirde uygulamanız sonunda bozulacaktır.
Fesleğen Bourque

1
Harika cevap! Buna ayırdığınız zaman için gerçekten minnettarım. :)
drognisep

ZoneId.of ("Amerika / Montreal"); neden birisi jdk'de böyle bir şey icat etsin? çirkin, iğrenç, çalışma zamanına kadar yanlış bir şey olup olmadığını söylememek, tüm bu sabit kodları kim hatırlayabilir? neden ENUM sınıfına dahil etmiyorsunuz?
workplaylifecycle

4

Java8'de, Instantzaten UTC'de olan ve çalışmak için uygun olan sınıfı kullanırdım .

import java.time.Instant;

Instant ins = Instant.now();
long ts = ins.toEpochMilli();

Instant ins2 = Instant.ofEpochMilli(ts)

Alternatif olarak, aşağıdakileri de kullanabilirsiniz:

import java.time.*;

Instant ins = Instant.now(); 

OffsetDateTime odt = ins.atOffset(ZoneOffset.UTC);
ZonedDateTime zdt = ins.atZone(ZoneId.of("UTC"));

Geri dön Instant

Instant ins4 = Instant.from(odt);

3
Hayır, bir Instantolduğunu değil yerel saate göre. Bir Instanttarafından tanım UTC içindedir. Dolayısıyla, bu Cevapta görülen UTC'ye girmeye çalışan entrikalara gerek yok; InstantZaten olan UTC. Bkz benim Answer fazla bilgi ve daha basit kodu.
Basil Bourque

Yorum için teşekkürler.
Abel Terefe


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.