Java에서 Long을 Date로 변환하면 1970이 반환됩니다.


119

웹 서비스에서 다운로드 한 긴 값 (예 : 1220227200, 1220832000, 1221436800 ...)이있는 목록이 있습니다. 날짜로 변환해야합니다. 안타깝게도이 방법은 다음과 같습니다.

Date d = new Date(1220227200);

1970 년 1 월 1 일을 반환합니다. 누구든지 올바르게 변환하는 다른 방법을 알고 있습니까?


기대하는 값이 무엇인지 말씀해 주시겠습니까? 초 / 밀리 초의 질문은 유효한 것일 수 있지만 1220227200은 1/1/1970이 아닙니다. 생성자에 0을 전달하는 것 같습니다. 더 많은 코드가 도움이 될 수 있습니다.
SJuan76 2011 년

1
@mmmiki - 당신은 대답을 받아 들여야
스튜어트

여기서는 1 월 1 일이 아니라 1970 년 1 월 15 일을 반환합니다.
njzk2

참고로, 같은 몹시 결함이 날짜 - 시간 수업 java.util.Date, java.util.Calendar그리고 java.text.SimpleDateFormat지금 기존 에 의해 대체, java.time의 나중에 자바 8에 내장 된 클래스.
Basil Bourque

답변:


161

Date생성자 (링크를 클릭!)와 같은 시간 허용 long에서 밀리 초 단위 가 아닌 초. 1000을 곱하고 long.

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

여기에 표시됩니다.

2008 년 8 월 31 일 일요일 20:00:00 GMT-04 : 00


22
또는 Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));더 깨끗하고 덜 마법 같은 솔루션을 사용하십시오.
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.

데이터 파악

사람들은 시대 이후로 시간을 추적 할 때 다양한 정밀도를 숫자로 사용합니다 . 따라서 에포크 이후 카운트로 해석 될 일부 숫자를 얻으려면 다음을 결정해야합니다.

  • 어떤 시대?
    많은 epochs 날짜 가 다양한 시스템에서 사용되었습니다. 일반적으로 사용되는 POSIX / Unix 시간 은 UTC로 1970 년의 첫 번째 순간입니다. 그러나이 시대를 가정 해서는 안됩니다 .
  • 무슨 정밀도? 에포크 이후로
    초, 밀리 초 , 마이크로 초 또는 나노초를 말하고 있습니까?
  • 어떤 시간대?
    일반적으로 epoch가 UTC / GMT 시간대이므로, 즉 시간대 오프셋이 전혀 없기 때문에 카운트 입니다. 그러나 때로는 경험이 없거나 날짜 시간에 무지한 프로그래머가 참여할 때 암시 된 시간대가있을 수 있습니다.

귀하의 경우 다른 사람들이 언급했듯이 Unix 시대 이후로 몇 초가 주어진 것 같습니다. 그러나 밀리 초를 예상하는 생성자에 해당 초를 전달합니다. 따라서 해결책은 1,000을 곱하는 것입니다.

교훈:

  • 수신 된 데이터의 의미를 결정하고 가정하지 마십시오.
  • 문서를 읽으십시오 .

전체 초, 밀리 초, 마이크로 초 및 나노초를 포함하여 날짜-시간 시스템의 다양한 해상도를 보여주는 그래프입니다.

귀하의 데이터

데이터가 몇 초 안에있는 것 같습니다. 1970 년 초를 가정하고 UTC 시간대를 가정하면 1,220,227,2002008 년 9 월 1 일의 첫 번째 순간입니다.

Joda-Time

Java와 함께 번들로 제공되는 java.util.Date 및 .Calendar 클래스는 문제가있는 것으로 악명이 높습니다. 그들을 피하십시오. 대신 Joda-Time 라이브러리 또는 Java 8에 번들로 제공되는 새로운 java.time 패키지 (Joda-Time에서 영감을 얻음)를 사용하십시오.

juDate와 달리 DateTimeJoda-Time의 a 는 자신에게 할당 된 시간대를 실제로 알고 있습니다 . 따라서 아래에 표시된 Joda-Time 2.4 코드 예제에서 먼저 기본 가정 인 UTC를 사용하여 밀리 초를 구문 분석합니다. 그런 다음 두 번째로 파리의 시간대를 조정하도록 지정합니다. 우주의 타임 라인에서 같은 순간이지만 벽시계 시간은 다릅니다 . 데모를 위해 다시 UTC로 조정합니다. 암시 적 기본값 (종종 날짜-시간 작업에서 문제의 원인)에 의존하는 것보다 원하는 / 예상 시간대를 명시 적으로 지정하는 것이 거의 항상 좋습니다.

DateTime을 생성하려면 밀리 초가 필요합니다. 따라서 초를 입력하고 천을 곱하십시오. long32 비트 오버플로가 발생하므로 결과는 64 비트 여야합니다 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".

생성자에 밀리 초 수를 입력합니다. 이 특정 생성자는 개수가 1970 년의 Unix 신기원이라고 가정합니다. 따라서 생성 후 원하는대로 시간대를 조정합니다.

적절한 시간대 이름, 대륙 및 도시 / 지역 조합을 사용하십시오 . EST표준화되지 않은 고유하지 않은 3 자 또는 4 자 코드를 사용하지 마십시오 .

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

데모를 위해 시간대를 다시 조정하십시오.

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

콘솔에 덤프합니다. 새로운 날이 유럽에서 시작되었지만 아직 미국에서는 시작되지 않았기 때문에 몬트리올에서 날짜가 어떻게 다른지 주목하십시오.

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

실행할 때.

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의 제작자들은 우리에게 편리한 즉시 그 대체품 인 java.time 프레임 워크로 마이그레이션 할 것을 요청했습니다 . Joda-Time은 계속해서 적극적으로 지원되지만 향후 모든 개발은 ThreeTen-Extra 프로젝트의 java.time 클래스 및 해당 확장에서 수행됩니다.

Java-time 프레임 워크는 JSR 310에 의해 정의 되고 Java 8 이상에 내장됩니다. java.time 클래스는 자바 6 & 7 백 포팅 된 ThreeTen - 백 포트의 에서 프로젝트와 안드로이드에 ThreeTenABP의 프로젝트.

An Instant은 나노초 단위 로 UTC 타임 라인의 한 순간입니다 . 그 시대는 1970 년 UTC의 첫 번째 순간입니다.

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

정보 적용 오프셋부터 UTC를 ZoneOffset 을 얻을 OffsetDateTime.

더 나은 방법은 알려진 경우 시간대 ZoneId를 적용 하여 ZonedDateTime.

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

Java의 모든 날짜-시간 유형 (현대 및 레거시 모두) 표


1
건배 친구. 훌륭한 설명입니다. 1970 년부터 새로운 DateTime (<long number>)을 얻었습니다. 내가 초 단위로 제공하고 밀리 초 단위로 필요하다는 것을 깨달았을 때
Suyash Dixit

40

longs는 밀리 초가 아니라 초인 것 같습니다. 날짜 생성자는 시간을 밀리 초로 사용하므로

Date d = new Date(timeInSeconds * 1000);

4
@ f1sh : 나는 반대표를 던지지 않았지만 원래 대답은 달랐습니다. 그는 5 분의 유예 기간 내에 그것을 편집했습니다.
BalusC 2011 년

설명해 주셔서 감사합니다. 그것은 자신의 단점입니다 SO가 ... :-/
f1sh

10

달력 개체의 시간을 밀 단위로만 설정하십시오.

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

그것들은 아마도 초 단위의 타임 스탬프이며 java new Date (long) 생성자에 필요한 밀리 초 단위 가 아닙니다 . 1000을 곱하면 괜찮습니다.


23
더 적절하게 30000 밀리 초가 너무 느림
SJuan76 2011 년

5

긴 값은 대부분 Epoch 타임 스탬프에 해당 하며 값은 다음과 같습니다.

1220227200 = 2008 년 9 월 1 일 월요일 00:00:00 GMT

1220832000 = 2008 년 9 월 8 일 월요일 00:00:00 GMT

1221436800 = 2008 년 9 월 15 일 월요일 00:00:00 GMT

이 긴 값을 java.util.Date 로 변환 할 수 있습니다. 이는 java.util.Date가 이전에 암시 한대로 millisecs를 사용하지만 다음과 같은 몇 가지 결함이 있다는 사실을 고려합니다.

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

이제 날짜를 올바르게 표시하기 위해 아래 그림과 같이 java.text.DateFormat을 사용할 수 있습니다.

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));

다음은 DateFormat을 사용 및 사용하지 않고 변환 된 long 값을 java.util.Date로 표시 한 결과입니다.

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

이 시도:

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

3

날짜 형식을 조정하여 시도해보십시오.

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

참고 : 24 시간 또는 12 시간주기를 확인하십시오.


2

1220227200은 1980 년 1 월 15 일에 해당하며 실제로 new Date (1220227200) .toString ()은 "Thu Jan 15 03:57:07 CET 1970"을 반환합니다. 긴 값을 1970 년 1 월 1 일 이전 인 날짜에 전달하면 실제로 1970 년 1 월 1 일의 날짜를 반환합니다. 값이이 상황에 있지 않은지 확인하십시오 (82800000 미만).


0

New Date (number)는 다음과 같은 날짜를 반환합니다. number 1970 년 1 월 1 일 이후 밀리 초인 . 날짜 형식은 1970 년 1 월 1 일 이후에 조금만 경과 한 것을 알 수 있도록 시간, 분, 초를 표시하지 않습니다.

올바른 구문 분석 라우팅에 따라 날짜를 구문 분석해야합니다. 1220227200이 무엇인지 모르겠지만 1970 년 1 월 1 일 이후 몇 초이면 곱하여 밀리 초를 산출합니다. 그렇지 않은 경우 1970 년 이후 밀리 초로 변환합니다 (java.util.Date를 계속 사용하려는 경우).


0

나를 위해 작동합니다. 당신이 얻은 것은 1970 년의 초이고 1970 년 1 월 1 일의 밀리 초를 통과해야하기 때문에 1000으로 곱하고 싶을 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.