Java 8'de LocalDateTime'dan milisaniye nasıl alınır


285

Yeni kullanarak 1-1-1970 (çağ) beri mevcut milisaniye almak için bir yol olup olmadığını merak ediyorum LocalDate , LocalTimeya LocalDateTimeJava 8'in sınıfları.

Bilinen yol aşağıdadır:

long currentMilliseconds = new Date().getTime();

veya

long currentMilliseconds = System.currentTimeMillis();

6
Sorun nedir System.currentTimeMillis()?
Dawood ibn Kareem

16
@DavidWallace Şu anki saati değil, bir Tarih saatini almaya çalışıyor mu?
Anubian Noob

2
"... mevcut milisaniyeyi elde etmenin bir yolu ..."
Dawood ibn Kareem

1-1-1970 arasında sayılan milisaniye. Java 8 LocalDate, LocalTime ve LocalDateTime yeni sınıflarını kullanarak onları almak için bir yöntem varsa dolaşıyordum, çünkü ben bulamadım.
George Siggouroglou

1
Bu sınıfların amacını anladığım zaman, bunun "insan odaklı" bir zaman anlayışı olması ve currentTimeMillisbu bağlamda alakasız olmasıdır. Takvim + Duvar Saati'ni gerçekten iyi bir hassasiyetle düşünün ve zaman dilimleri ve yerellik hakkında endişelenmeyin. Bu yüzden LocalTime'dan "UTC Saati" ne geri dönmenin bir yolu yok
Gus

Yanıtlar:


325

"Şu anki milisaniye" ile ne demek istediğinizi tam olarak bilmiyorum ama "çağ" dan bu yana geçen milisaniye sayısı, yani gece yarısı, 1 Ocak 1970 UTC.

Şu andan bu yana geçen milisaniye sayısını bulmak istiyorsanız , Anubian Noob'un işaret ettiğiSystem.currentTimeMillis() gibi kullanın . Öyleyse, bunu yapmak için yeni java.time API'lerinden herhangi birini kullanmanız için hiçbir neden yoktur.

Ancak, belki zaten bir LocalDateTimeyerden bir veya benzer bir nesneniz var ve onu çağdan beri milisaniyeye dönüştürmek istiyorsunuz. Bunu yapmak doğrudan mümkün değildir, çünkü LocalDateTimenesne ailesinin içinde bulundukları saat dilimi hakkında bir fikri yoktur. Bu nedenle UTC'de olan döneme göre zamanı bulmak için zaman dilimi bilgilerinin sağlanması gerekir.

Diyelim ki böyle bir şeye sahipsiniz LocalDateTime:

LocalDateTime ldt = LocalDateTime.of(2014, 5, 29, 18, 41, 16);

Saat dilimi bilgilerini uygulamanız gerekir ZonedDateTime. Los Angeles ile aynı saat dilimindeyim, bu yüzden böyle bir şey yapardım:

ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/Los_Angeles"));

Tabii ki, bu zaman dilimi hakkında varsayımlar yapar. Örneğin, yerel saatin Yaz Saati uygulamasına yakın bir saati adlandırması durumunda oluşabilecek uç durumlar vardır. Bunları bir kenara bırakalım, ancak bu vakaların var olduğunun farkında olmalısınız.

Her neyse, geçerli bir tane ZonedDateTimealabiliyorsanız, bu dönemi çağdan bu yana geçen milisaniye sayısına dönüştürebilirsiniz, şöyle:

long millis = zdt.toInstant().toEpochMilli();

5
Not ZonedDateTime zaten sahiptirgetEpochSecond (aracılığıyla yöntemi ChronoZonedDateTime varsayılan ). Gerek yok Instant.
mabi

14
Tabii, tek ihtiyacınız milisaniye değil saniye.
Stuart Marks

1
Ah, kesin değilim: ZonedDateTime Ayrıca sahiptir Instants getNanoyöntem, bu nedenle sadece yerine mümkün olmaz instile zdtsizin örnekte?
mabi

18
Zdt.get (ChronoField.MILLI_OF_SECOND) kullanarak nanos'taki matematikten kaçının. Zdt.toInstant () kullanarak tüm matematiklerden kaçının. ToEpochMilli ()
JodaStephen

1
Her neyse, hem siz hem de @walen yorum yaptıkları için, yanıltıcı insanları önlemek için şimdi orijinal mesajlarımı silmeye karar verdim.
Per Lundberg

81

Ne yaptığımı bir saat dilimi belirtmiyorum,

System.out.println("ldt " + LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
System.out.println("ctm " + System.currentTimeMillis());

verir

ldt 1424812121078 
ctm 1424812121281

Gördüğünüz gibi, sayılar küçük bir yürütme süresi dışında aynıdır.

System.currentTimeMillis'i beğenmemeniz durumunda, Instant.now().toEpochMilli()


3
Hayır, Epoch UTC'ye göredir ancak geçerli saati yerel bölgenizden alırsınız.
Rafael Membrives

2
@ ChristofferHammarström dönemden bu yana geçen milisaniye miktarı, saat diliminden bağımsız bir gerçektir. Günün hangi saati diyor olursanız olun, aynı milisaniye miktarı. İki sonuç farklıdır, çünkü brian'ın makinesi ikinci komutu yürütmek için 203 milisaniye sürdü.
Fletch

Kullanıcı farklı bir saat diliminde UTC kullanmakta sorun yok
GilbertS

2
@GilbertS muhtemelen bu kodu asla kullanmamalısınız, API'yi istendiği gibi kullanmalısınız. Bir bilgisayarda saklandığında veya başka bir kullanıcıya aktarıldığında tarih ve saat her zaman UTC olmalıdır. Genellikle kullanıcıya kendi saat dilimi ayarları kullanılarak yerel bir tarih saati olarak sunulmalıdır.
brian

20

ZoneId'den kaçınmak için şunları yapabilirsiniz:

LocalDateTime date = LocalDateTime.of(1970, 1, 1, 0, 0);

System.out.println("Initial Epoch (TimeInMillis): " + date.toInstant(ZoneOffset.ofTotalSeconds(0)).toEpochMilli());

Değer olarak 0 almak doğru!


8
ZoneOffset.ofTotalSeconds(0)AynıZoneOffset.UTC
Anton Novopashin

1
Evet, bu benim AntonNovopashin'nin yorumunu düzeltiyordu. UTC'ye ihtiyacınız olduğundan, iyisiniz (yanıtta bundan bahsetmek isteyebilirsiniz). BTW ZoneOffsetbir alt sınıftır ZoneId, bu yüzden bundan kaçındığınızı söyleyemem, ama mutlu olduğunuz sürece ...
Ole VV

İlk yorumum biraz sertti, ama saldırgan değildi. Saldırdınız. Üzgünüm. Sildim. Başka türlü sormama izin ver: kaçınmak istememizin nedeni ne olabilir ZoneId?
Ole VV

@ OleV.V UTC kullanmak uygun mudur? Sadece UTC saat diliminde yaşayan insanlar için değil.
GilbertS

1
@GilbertS Kimsenin UTC saat diliminde yaşadığını sanmıyorum. Saat dilimlerinde kullanılan saatler için UTC kullanılması iyi bir uygulama olarak önerilir. Örneğin , Coğrafi Olarak Farklı Kullanıcılar için Tarih İşleme / Depolama için Java En İyi Uygulaması'na bakın . Ya da belki sorunuzu anlamadım?
Ole VV

15

Java 8'den beri arayabilirsiniz java.time.Instant.toEpochMilli().

Örneğin çağrı

final long currentTimeJava8 = Instant.now().toEpochMilli();

size aynı sonuçları verir

final long currentTimeJava1 = System.currentTimeMillis();

1
"size aynı sonuçları verir" ... ancak daha fazla CPU gücü alır ve çöp toplayıcıyı çok daha fazla vurgular.
VasiliNovikov

1
Yukarıda sayılanları görmek istiyorum (özellikle normal kullanım için - örneğin, bazı performans kritik gerçek zamanlı uygulamalar için değil ...)
Brian Agnew

11

java.sql.TimestampMilisaniye almak için de kullanabilirsiniz .

LocalDateTime now = LocalDateTime.now();
long milliSeconds = Timestamp.valueOf(now).getTime();
System.out.println("MilliSeconds: "+milliSeconds);

Bir saat dilimi için önemli ihtiyacı görmezden geliyorsunuz. Bu şekilde yapmanızı önermiyorum. Ayrıca Timestampsınıf uzun modası geçmiş ve tasarım sorunları ile dolu, bu yüzden özellikle sınıfları java.timegibi kullanabilirsiniz zaman önlemek istiyorum LocalDateTime.
Ole VV

@ OleV.V. Sadece tasarım problemlerini merak ediyorum Timestamp, Bununla ilgili bir makale paylaşabilir misiniz? Kodumdan da kullanmaktan kaçınmamı sağlıyor Timestamp. Teşekkürler!
Nalam

1
Sadece kısa, bir alt sınıf olarak uygulanır, Dateancak genellikle a olarak ele alınamaz Date. DateBir yapıcıdan miras alınan yöntemlerin çoğu kullanımdan kaldırılmıştır. Bu toStringyöntem, aynı yana birçok karıştırır JVM zaman dilimini kullanır Timestampfarklı bilgisayarlar (farklı şekilde basılır , örneğin ).
Ole VV

Bu, birim testi için mükemmeldir. Şimdi şimdi yerineLocalDate.of(year, month, day)
G_V

Bu, "her zaman UTC" değerlerine geçici bir çözüm bulmak için kabul edilen yanıt olmalıdır.
LeYAUable

9

Geçerli saati milisaniye olarak almak için (çağdan beri), tuşunu kullanın System.currentTimeMillis().


3

Bir Java 8 Saatiniz varsa, clock.millis() ( öneririm)clock.instant() daha doğru olduğu için bir Java 8 Anında Arama'yı ).

Neden bir Java 8 saati kullanasınız? DI çerçevenizde bir Saat çekirdeği oluşturabilirsiniz:

@Bean
public Clock getClock() {
    return Clock.systemUTC();
}

ve sonra testlerinizde kolayca alay edebilirsiniz:

@MockBean private Clock clock;

ya da farklı bir fasülye sahip olabilirsiniz:

@Bean
public Clock getClock() {
    return Clock.fixed(instant, zone);
}

bu da tarihleri ​​ve saatleri ölçülemez bir şekilde iddia eden testlere yardımcı olur.


1
  default LocalDateTime getDateFromLong(long timestamp) {
    try {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneOffset.UTC);
    } catch (DateTimeException tdException) {
      //  throw new 
    }
}

default Long getLongFromDateTime(LocalDateTime dateTime) {
    return dateTime.atOffset(ZoneOffset.UTC).toInstant().toEpochMilli();
}

0

Neden kimse yöntemden bahsetmedi LocalDateTime.toEpochSecond():

LocalDateTime localDateTime = ... // whatever e.g. LocalDateTime.now()
long time2epoch = localDateTime.toEpochSecond(ZoneOffset.UTC);

Bu, yukarıdaki birçok cevaptan çok daha kısa görünüyor ...


Aradığım şey buydu. Kabul edilen cevap bana willies veriyordu.
Brill Pappin

Yalnızca API 26'da kullanılabilir
olanı

1
Çünkü sadece saniyeler veriyor. toEpochMilliLocalDateTime'da nanosaniye bile belirtebileceğiniz göz önüne alındığında , bir yöntem olmaması garip : bir yöntem var LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond).
izogfif
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.