LocalDate ve LocalDateTime'dan dönem nasıl çıkarılır?


103

Veya Longörneklerinden epoch değerini nasıl alırım ? Aşağıdakileri denedim, ancak bana başka sonuçlar veriyor:LocalDateTimeLocalDate

LocalDateTime time = LocalDateTime.parse("04.02.2014  19:51:01", DateTimeFormatter.ofPattern("dd.MM.yyyy  HH:mm:ss"));
System.out.println(time.getLong(ChronoField.SECOND_OF_DAY)); // gives 71461
System.out.println(time.getLong(ChronoField.EPOCH_DAY)); // gives 16105

İstediğim şey 1391539861, yerel tarih saatinin değeri "04.02.2014 19:51:01". Europe/OsloSaat dilimim UTC + 1 ve gün ışığından yararlanma saati.


Lütfen tahmini numaranızı açıklayın 1396468261. Saat dilimi düzeltmesi olmadan alıyorum: 1391543461 (cevabımdaki düzenlemeye bakın). 57 gün fark!
Meno Hochschild

@MenoHochschild Sorum saat dilimi bilgisiyle güncelledim ve GTM'den yerel zamana gerçek değeri düzelttim. LocalDateTimeEl ile hesaplamaktan başka bir dönemin dönemini öğrenmenin daha kolay bir yolu var mı ?

Duraklamamdan geri dönüyorum, güncellememe bakın.
Meno Hochschild

Yanıtlar:


149

Sınıflar LocalDateve saat dilimi veya zaman farkıLocalDateTime hakkında bilgi içermez ve bu bilgi olmadan dönemin belirsiz olacağı saniyeler. Bununla birlikte, nesnelerin, bir örneği geçerek saat dilimlerine sahip tarih / saat nesnelerine dönüştürmek için çeşitli yöntemleri vardır .ZoneId

Yerel Tarih

LocalDate date = ...;
ZoneId zoneId = ZoneId.systemDefault(); // or: ZoneId.of("Europe/Oslo");
long epoch = date.atStartOfDay(zoneId).toEpochSecond();

LocalDateTime

LocalDateTime time = ...;
ZoneId zoneId = ZoneId.systemDefault(); // or: ZoneId.of("Europe/Oslo");
long epoch = time.atZone(zoneId).toEpochSecond();

2
ZoneId kullanmaktan kaçınmak veya özelleştirilmiş, sabit ZoneId örneğiyle (+0, GMT anlamına gelir) kullanmaktan kaçınmak mümkün müdür? Bunu soruyorum çünkü tüm hesaplamaların normalleştirilmesini istiyorum. Ayrıca, bunun tam tersini nasıl yapabilirim: dönem zamanından LocalDate / LocalDateTime'a dönüştürme (ayrıca ZoneId olmadan veya GMT olanla)?
android geliştiricisi

2
Boşver. Buldum:ZoneId.ofOffset("UTC", ZoneOffset.ofHours(0))
android geliştiricisi

7
Daha basit bir yaklaşım, yalnızca long epoch = time.toEpochSecond(ZoneOffset.UTC)UTC durumları için veya saat dilimini zaten bildiğiniz yerler veya long epoch = time.toEpochSecond(ZoneId.systemDefault());bu rotaya gitmek istiyorsanız.
Marcus

Bu saçma gelebilir ama nasıl LOCALDATE, localtime'a & LocalDateTime için dönemin dönüştürme arka yaklaşık
owino samuel

Boşver, bulduğumu düşünüyorum; Instant.ofEpochMilli(responseTime).atZone(ZoneId.systemDefault()).toLocalTime()
samuel owino

27

'Unix döneminden beri milis' bir anı temsil eder, bu nedenle Instant sınıfını kullanmalısınız:

private long toEpochMilli(LocalDateTime localDateTime)
{
  return localDateTime.atZone(ZoneId.systemDefault())
    .toInstant().toEpochMilli();
}

kullanımı yanlıştır ZoneId.systemDefault()çünkü unix dönemi UTC
ACV

10

İhtiyacınız olan dönüştürme, UTC / Greewich'ten fark veya bir saat dilimi gerektirir.

Eğer bir ofset varsa, bir orada adanmış yöntem üzerinde LocalDateTimebu görev için:

long epochSec = localDateTime.toEpochSecond(zoneOffset);

Yalnızca varsa ZoneIdo zaman elde edebilirsiniz ZoneOffsetdan ZoneId:

ZoneOffset zoneOffset = ZoneId.of("Europe/Oslo").getRules().getOffset(ldt);

Ancak dönüşümü ZonedDateTimedaha basit bir yolla bulabilirsiniz :

long epochSec = ldt.atZone(zoneId).toEpochSecond();

4
Sadece long epochSec = localDateTime.toEpochSecond(ZoneOffset.UTC);
UTC'yi önemsiyorsanız

2

Hangi alanların desteklendiğini görmek için bu yönteme bakın. Bulacaksın LocalDateTime:

NANO_OF_SECOND 
NANO_OF_DAY 
MICRO_OF_SECOND 
MICRO_OF_DAY 
MILLI_OF_SECOND 
MILLI_OF_DAY 
SECOND_OF_MINUTE 
SECOND_OF_DAY 
MINUTE_OF_HOUR 
MINUTE_OF_DAY 
HOUR_OF_AMPM 
CLOCK_HOUR_OF_AMPM 
HOUR_OF_DAY 
CLOCK_HOUR_OF_DAY 
AMPM_OF_DAY 
DAY_OF_WEEK 
ALIGNED_DAY_OF_WEEK_IN_MONTH 
ALIGNED_DAY_OF_WEEK_IN_YEAR 
DAY_OF_MONTH 
DAY_OF_YEAR 
EPOCH_DAY 
ALIGNED_WEEK_OF_MONTH 
ALIGNED_WEEK_OF_YEAR 
MONTH_OF_YEAR 
PROLEPTIC_MONTH 
YEAR_OF_ERA 
YEAR 
ERA 

INSTANT_SECONDS alanı - elbette - desteklenmez çünkü LocalDateTimeherhangi bir mutlak (global) zaman damgasına atıfta bulunamaz. Ancak yardımcı olan, 1970-01-01'den bu yana geçen günleri sayan EPOCH_DAY alanıdır . Benzer düşünceler tür için de geçerlidir LocalDate(daha az desteklenen alanlar ile).

Mevcut olmayan milis-beri-unix-epoch alanını almayı düşünüyorsanız, yerelden global türe dönüştürmek için zaman dilimine de ihtiyacınız vardır. Bu dönüşüm çok daha basit bir şekilde yapılabilir, diğer SO-gönderilerine bakın .

Sorunuza ve kodunuzdaki sayılara geri dönersek:

The result 1605 is correct
  => (2014 - 1970) * 365 + 11 (leap days) + 31 (in january 2014) + 3 (in february 2014)
The result 71461 is also correct => 19 * 3600 + 51 * 60 + 1

16105L * 86400 + 71461 = 1391543461 saniye 1970-01-01T00: 00: 00'dan beri (dikkat, saat dilimi yok) Daha sonra saat dilimi uzaklığını çıkarabilirsiniz (milisaniye cinsinden 1000 ile olası çarpmaya dikkat edin).

Saat dilimi bilgisi verildikten sonra UPDATE:

local time = 1391543461 secs
offset = 3600 secs (Europe/Oslo, winter time in february)
utc = 1391543461 - 3600 = 1391539861

İki eşdeğer yaklaşımla JSR-310 kodu olarak:

long secondsSinceUnixEpoch1 =
  LocalDateTime.of(2014, 2, 4, 19, 51, 1).atZone(ZoneId.of("Europe/Oslo")).toEpochSecond();

long secondsSinceUnixEpoch2 =
  LocalDate
    .of(2014, 2, 4)
    .atTime(19, 51, 1)
    .atZone(ZoneId.of("Europe/Oslo"))
    .toEpochSecond();

1
Açıklama için teşekkürler. LocalDateTime time = LocalDateTime.parse("04.02.2014 19:51:01", DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"));Ve sonra kullanarak doğru sonucu aldım Long epoch = time.atZone(ZoneId.of("Europe/Oslo")).toEpochSecond();.

1

İnsan tarafından okunabilir tarihten döneme dönüştür :

long epoch = new java.text.SimpleDateFormat("MM/dd/yyyyHH:mm:ss").parse("01/01/1970 01:00:00").getTime() / 1000;

Dönemden okunabilir tarihe dönüştürün :

String date = new java.text.SimpleDateFormat("MM/dd/yyyyHH:mm:ss").format(new java.util.Date (epoch*1000));

Diğer dil dönüştürücü için: https://www.epochconverter.com


0

Bu, zaman dilimi kullanmadan bir yoldur:

LocalDateTime now = LocalDateTime.now();
long epoch = (now.getLong(ChronoField.EPOCH_DAY) * 86400000) + now.getLong(ChronoField.MILLI_OF_DAY);
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.