Java'da Uzun Tarihe Dönüştürmek 1970'i döndürür


119

Web servisinden indirdiğim uzun değerlere sahip listem var (örneğin: 1220227200, 1220832000, 1221436800 ...). Bunu Dates'e çevirmeliyim. Maalesef bu şekilde, örneğin:

Date d = new Date(1220227200);

1 Ocak 1970'i döndürür. Bunu doğru şekilde dönüştürmek için başka bir yol bilen var mı?


Hangi değerleri beklediğinizi söyleyebilir misiniz? Saniye / milisaniye sorusu geçerli olabilir, ancak 1220227200 1/1/1970 değildir. Yapıcıya 0 veriyor gibi görünüyor. Biraz daha kod yardımcı olabilir.
SJuan76

1
@mmmiki - bir cevabı kabul etmelisiniz
Stewart

15 Ocak 1970'e dönüyor, 1 Ocak değil burada.
njzk2

Bilginize gibi korkunç kusurlu tarih-saat sınıfları java.util.Date, java.util.Calendarve java.text.SimpleDateFormatşimdi mirası supplanted, java.time sonra Java 8 ve yerleşik sınıflara.
Basil Bourque

Yanıtlar:


161

DateYapıcı (bağlantıyı tıklayın!) Olarak zaman kabul longyılında milisaniye değil, saniye. Bunu 1000 ile çarpmanız ve olarak verdiğinizden emin olmanız gerekir long.

Date d = new Date(1220227200L * 1000);

Bu burada gösterir

31 Ağustos Paz 20:00:00 GMT-04: 00 2008


22
Veya alternatif olarak, Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));daha temiz ve daha az sihirli sayıya sahip bir çözüm için kullanın.
Priidu Neemre

56

tl; Dr.

java.time.Instant                    // Represent a moment as seen in UTC. Internally, a count of nanoseconds since 1970-01-01T00:00Z.
.ofEpochSecond( 1_220_227_200L )     // Pass a count of whole seconds since the same epoch reference of 1970-01-01T00:00Z.

Verilerinizi Tanıyın

İnsanlar, bir çağdan beri bir sayı olarak izleme süresinde çeşitli hassasiyetler kullanırlar . Bu nedenle, bir dönemden beri sayım olarak yorumlanacak bazı sayılar elde ettiğinizde, şunları belirlemelisiniz:

  • Hangi dönem? Çeşitli sistemlerde
    birçok çağ tarihi kullanılmıştır. Yaygın olarak kullanılan POSIX / Unix zamanıdır , burada dönem UTC'de 1970'in ilk anıdır. Ama bu dönemi üstlenmemelisiniz .
  • Ne hassasiyeti? Çağdan beri
    saniyeler, milisaniyeler , mikrosaniyeler veya nanosaniyelerden mi bahsediyoruz ?
  • Hangi saat dilimi? Zaman dilimi UTC / GMT saat diliminde
    olduğu için genellikle bir sayım , yani saat dilimi farkı yoktur. Ancak bazen deneyimsiz veya tarih-zaman bilgisine sahip olmayan programcılar söz konusu olduğunda, zımni bir saat dilimi olabilir.

Sizin durumunuzda, diğerlerinin de belirttiği gibi, Unix döneminden bu yana size saniyeler verildi. Ancak bu saniyeleri milisaniyeler bekleyen bir kurucuya geçiriyorsunuz. Yani çözüm 1000 ile çarpmaktır.

Dersler öğrenildi:

  • Alınan verilerin anlamını belirleyin, varsaymayın.
  • Dokümanı okuyun .

Tam saniye, milisaniye, mikrosaniye ve nanosaniye dahil olmak üzere tarih-saat sistemlerinde çeşitli çözünürlük ayrıntılarını gösteren grafik.

Verileriniz

Verileriniz saniyeler içinde görünüyor. 1970'in başlangıcını varsayarsak ve UTC zaman dilimini varsayarsak, o zaman 1,220,227,200Eylül 2008'in ilk gününün ilk anıdır.

Joda-Time

Java ile birlikte verilen java.util.Date ve .Calendar sınıfları, herkesin bildiği gibi zahmetlidir. Onlardan kaçının. Bunun yerine Joda-Time kitaplığını veya Java 8'de paketlenen (ve Joda-Time'dan esinlenen) yeni java.time paketini kullanın .

JuDate'ten farklı olarak, DateTimeJoda-Time'da a'nın kendi atanmış zaman dilimini gerçekten bildiğini unutmayın . Bu nedenle, aşağıda görülen örnek Joda-Time 2.4 kodunda, önce varsayılan UTC varsayımını kullanarak milisaniyeleri ayrıştırdığımıza dikkat edin. Ardından, ikinci olarak, ayarlanacak bir Paris saat dilimi atarız. Evrenin zaman çizelgesinde aynı an, ancak farklı duvar saati zamanı . Gösteri için tekrar UTC'ye ayarlıyoruz. İstediğiniz / beklenen saat dilimini açıkça belirtmek, örtük bir varsayılana (genellikle tarih-saat çalışmasındaki sorunun nedeni) güvenmek yerine, hemen hemen her zaman daha iyidir.

Bir DateTime oluşturmak için milisaniyeye ihtiyacımız var. Öyleyse, saniye girdinizi alın ve bin ile çarpın. long32-bit'i aşacağımız için sonucun 64-bit olması gerektiğini unutmayın int.

long input = 1_220_227_200L;  // Note the "L" appended to long integer literals.
long milliseconds = ( input * 1_000L ); // Use a "long", not the usual "int". Note the appended "L".

Yapıcıya milisaniye sayısını besleyin. Söz konusu kurucu, sayının 1970 Unix döneminden olduğunu varsayar. Bu nedenle, inşaattan sonra saat dilimini istediğiniz gibi ayarlayın.

Uygun saat dilimi adlarını, kıta ve şehir / bölge kombinasyonunu kullanın . ESTStandartlaştırılmadıkları veya benzersiz olmadığı için asla 3 veya 4 harfli kodlar kullanmayın .

DateTime dateTimeParis = new DateTime( milliseconds ).withZone( DateTimeZone.forID( "Europe/Paris" ) );

Gösteri için saat dilimini tekrar ayarlayın.

DateTime dateTimeUtc = dateTimeParis.withZone( DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeParis.withZone( DateTimeZone.forID( "America/Montreal" ) );

Konsola boşaltın. Yeni gün Avrupa'da başladı ama henüz Amerika'da olmadığı için Montréal'de tarihin ne kadar farklı olduğuna dikkat edin.

System.out.println( "dateTimeParis: " + dateTimeParis );
System.out.println( "dateTimeUTC: " + dateTimeUtc );
System.out.println( "dateTimeMontréal: " + dateTimeMontréal );

Çalıştırıldığında.

dateTimeParis: 2008-09-01T02:00:00.000+02:00
dateTimeUTC: 2008-09-01T00:00:00.000Z
dateTimeMontréal: 2008-08-31T20:00:00.000-04:00

java.time

Joda-Time'ın yapımcıları , uygun olan en kısa sürede onun yerine geçen java.time çerçevesine geçmemizi istediler . Joda-Time aktif olarak desteklenmeye devam ederken, gelecekteki tüm geliştirmeler java.time sınıfları ve ThreeTen-Extra projesindeki uzantıları üzerinde yapılacaktır.

Java zamanı çerçevesi, JSR 310 tarafından tanımlanır ve Java 8 ve sonrasında yerleşiktir. Java.time sınıfları, ThreeTen-Backport projesinde Java 6 ve 7'ye ve ThreeTenABP projesinde Android'e geri taşındı .

An Instant, nanosaniye çözünürlükle UTC'de zaman çizelgesindeki bir andır . Çağı, UTC'de 1970'in ilk anıdır.

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

UTC'den sapma uygulayarak ZoneOffsetbir OffsetDateTime.

Daha da iyisi, eğer biliniyorsa, ZoneIdbir ZonedDateTime.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

Hem modern hem de eski Java'daki tüm tarih-saat türlerinin tablosu


1
Şerefe dostum. Harika açıklama. Saniyeler içinde
verdiğimi

40

Görünüşe göre uzun süreleriniz milisaniye değil saniye. Tarih oluşturucu zamanı milis olarak alır, bu nedenle

Date d = new Date(timeInSeconds * 1000);

4
@ f1sh: Olumsuz oy vermedim, ancak orijinal cevap farklıydı. 5 dakikalık ödemesiz süre içinde düzenledi.
BalusC

açıklama için teşekkürler. Bu, SO'nun kendisinin dezavantajı ...: - /
f1sh

10

Yalnızca Takvim nesnesindeki değirmenlerde saati ayarlayın

Calendar c = Calendar.getInstance();
c.setTimeInMillis(1385355600000l);
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.get(Calendar.MONTH));
System.out.println(c.get(Calendar.DAY_OF_MONTH));
// get Date
System.out.println(c.getTime());

9

Bunlar muhtemelen saniye cinsinden zaman damgalarıdır ve java new Date (uzun) kurucusu için gerekli olan milisaniye cinsinden değildir . Onları 1000 ile çarp ve iyi olmalısın.


23
daha düzgün 30000 milisaniye çok yavaş
SJuan76

5

Uzun değerler büyük olasılıkla Epoch zaman damgalarına karşılık gelir ve değerler şunlardır:

1220227200 = 01 Eylül 2008 Pzt 00:00:00 GMT

1220832000 = Pzt, 08 Eylül 2008 00:00:00 GMT

1221436800 = Pzt, 15 Eylül 2008 00:00:00 GMT

Bu uzun değerleri java.util.Date'e çevirebiliriz, java.util.Date'in daha önce ima edildiği gibi, ancak bazı kusurları olduğu gerçeğini hesaba katarak, aşağıdaki gibi:

// note: enforcing long literals (L), without it the values would just be wrong.
Date date = new Date(1220227200L * 1000L); 

Şimdi, tarihi doğru bir şekilde görüntülemek için, aşağıda gösterildiği gibi java.text.DateFormat kullanılabilir:

DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("Wrong date time value: " + date);
System.out.println("Correct date time value: " + df.format(date));

Aşağıda, DateFormat kullanmadan ve kullanmadan java.util.Date'e dönüştürülen uzun değeri görüntülemenin sonuçları verilmiştir:

Date wrong (off by 2 hours): Mon Sep 01 02:00:00 CEST 2008
Correct date : Monday, 1 September 2008 00:00:00 o'clock UTC

4

Bunu dene:

Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1220227200 * 1000);
System.out.println(cal.getTime());

3

Bunu tarih formatını ayarlayarak deneyin.

long longtime = 1212580300;
SimpleDateFormat dateFormat = new SimpleDateFormat("MMddyyHHmm");
Date date = (Date) dateFormat.parseObject(longtime + "");
System.out.println(date);

Not: 24 saatlik veya 12 saatlik döngüyü kontrol edin.


2

1220227200, 15 Ocak 1980'e karşılık gelir (ve gerçekten de yeni Tarih (1220227200) .toString (), "15 Ocak 03:57:07 CET 1970" döndürür). Bir tarihe uzun bir değer iletirseniz, yani 01/01/1970 tarihinden önce, aslında 01/01/1970 tarihini döndürecektir. Değerlerinizin bu durumda olmadığından emin olun (82800000'den düşük).


0

Yeni Tarih (sayı) number1 Ocak 1970'ten sonra milisaniye olan bir tarihi döndürür. Muhtemelen tarih formatınız saat, dakika ve saniye olarak 1 Ocak 1970'ten biraz sonra olduğunu görmüyorsunuz.

Tarihi, doğru ayrıştırma rotasına göre ayrıştırmanız gerekir. 1220227200'ün ne olduğunu bilmiyorum, ancak 1 OCAK 1970'den sonra saniyelerse, milisaniye elde etmek için çarpın. Değilse, 1970'den sonra bir şekilde milisaniyeye dönüştürün (java.util.Date'i kullanmaya devam etmek istiyorsanız).


0

Benim için çalışıyor. Muhtemelen 1000 ile multiplz yapmak istersiniz, çünkü elde ettiğiniz şey 1970'den saniyelerdir ve 1 Ocak 1970'den itibaren milisaniyeleri geçmek zorundasınız.

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.