IT박스

'Z'리터럴로 날짜를 구문 분석하는 simpledateformat

itboxs 2020. 10. 26. 07:48
반응형

'Z'리터럴로 날짜를 구문 분석하는 simpledateformat


이 질문에 이미 답변이 있습니다.

다음과 같은 날짜를 구문 분석하려고합니다.

2010-04-05T17:16:00Z

http://www.ietf.org/rfc/rfc3339.txt에 따라 유효한 날짜입니다 . 'Z'리터럴은 "UTC가 지정된 시간 동안 선호되는 참조 지점임을 암시합니다."

SimpleDateFormat과이 패턴을 사용하여 구문 분석하려고하면 :

yyyy-MM-dd'T'HH:mm:ss

Mon Apr 05 17:16:00 EDT 2010으로 구문 분석됩니다.

SimpleDateFormat은 다음 패턴으로 문자열을 구문 분석 할 수 없습니다.

yyyy-MM-dd'T'HH:mm:ssz
yyyy-MM-dd'T'HH:mm:ssZ

예상 출력을 얻기 위해 SimpleDateFormat에서 사용할 TimeZone을 명시 적으로 설정할 수 있지만 이것이 필요하다고 생각하지 않습니다. 내가 놓친 것이 있습니까? 대체 날짜 파서가 있습니까?


패턴에서 'z'날짜-시간 구성 요소를 포함하면 시간대 형식이 일반 시간대 '표준' 을 준수해야 함을 나타냅니다 Pacific Standard Time; PST; GMT-08:00. 예는 .

'Z'는 시간대가 RFC 822 시간대 표준 (예 : -0800.

DatatypeConverter가 필요하다고 생각합니다 ...

@Test
public void testTimezoneIsGreenwichMeanTime() throws ParseException {
    final Calendar calendar = javax.xml.bind.DatatypeConverter.parseDateTime("2010-04-05T17:16:00Z");
    TestCase.assertEquals("gotten timezone", "GMT+00:00", calendar.getTimeZone().getID());
}

Java는 ISO 날짜를 올바르게 구문 분석하지 않습니다.

McKenzie의 답변과 유사합니다.

Z파싱하기 전에 수정하십시오 .

암호

String string = "2013-03-05T18:05:05.000Z";
String defaultTimezone = TimeZone.getDefault().getID();
Date date = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).parse(string.replaceAll("Z$", "+0000"));

System.out.println("string: " + string);
System.out.println("defaultTimezone: " + defaultTimezone);
System.out.println("date: " + (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).format(date));

결과

string: 2013-03-05T18:05:05.000Z
defaultTimezone: America/New_York
date: 2013-03-05T13:05:05.000-0500

구문 분석중인 날짜는 ISO8601 형식입니다.

Java 7에서 시간대 접미사를 읽고 적용하는 패턴은 다음과 같아야합니다. yyyy-MM-dd'T'HH:mm:ssX


tl; dr

Instant.parse ( "2010-04-05T17:16:00Z" )

ISO 8601 표준

문자열은 ISO 8601 표준을 준수합니다 (여기서 언급 된 RFC 3339 는 프로필입니다).

juDate 피하기

Java와 함께 번들로 제공되는 java.util.Date 및 .Calendar 클래스는 문제가있는 것으로 악명이 높습니다. 그들을 피하십시오.

대신 Joda-Time 라이브러리 또는 Java 8의 새로운 java.time 패키지를 사용하십시오. 둘 다 날짜-시간 값의 문자열 표현을 구문 분석하고 생성하기위한 기본값으로 ISO 8601을 사용합니다.

java.time

Java 8 이상에 내장 java.time 프레임 워크는 성가신 이전 java.util.Date/.Calendar 클래스를 대체합니다. 새로운 클래스는 개념이 비슷하지만 재 설계된 후임자로 의도 된 매우 성공적인 Joda-Time 프레임 워크에서 영감을 얻었습니다 . JSR 310에 의해 정의되었습니다 . ThreeTen-Extra 프로젝트에 의해 확장되었습니다 . 튜토리얼을 참조하십시오 .

Instantjava.time 클래스는 UTC 시간대 의 타임 라인에서 순간을 나타냅니다 .

Z하여 입력 문자열 수단의 끝 Zulu을 의미합니다 UTC. 이러한 문자열은 Instant포맷터를 지정할 필요없이 클래스에서 직접 구문 분석 할 수 있습니다 .

String input = "2010-04-05T17:16:00Z";
Instant instant = Instant.parse ( input );

콘솔에 덤프합니다.

System.out.println ( "instant: " + instant );

즉시 : 2010-04-05T17 : 16 : 00Z

거기에서 시간대 ( ZoneId)를 적용 Instant하여 ZonedDateTime. 토론 및 예를 보려면 Stack Overflow를 검색하세요.

java.util.Date객체 를 사용해야하는 경우 정적 메서드와 같이 이전 클래스에 추가 된 새 변환 메서드를 호출하여 변환 할 수 있습니다 java.util.Date.from( Instant ).

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

Joda-Time

Joda-Time 2.5의 예.

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ):
DateTime dateTime = new DateTime( "2010-04-05T17:16:00Z", timeZone );

UTC로 변환하십시오.

DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );

필요한 경우 java.util.Date로 변환하십시오.

java.util.Date date = dateTime.toDate();

According to last row on the Date and Time Patterns table of the Java 7 API

X Time zone ISO 8601 time zone -08; -0800; -08:00

For ISO 8601 time zone you should use:

  • X for (-08 or Z),
  • XX for (-0800 or Z),
  • XXX for (-08:00 or Z);

so to parse your "2010-04-05T17:16:00Z" you can use either "yyyy-MM-dd'T'HH:mm:ssX" or "yyyy-MM-dd'T'HH:mm:ssXX" or "yyyy-MM-dd'T'HH:mm:ssXXX" .

    System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").parse("2010-04-05T17:16:00Z"));
    System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXX").parse("2010-04-05T17:16:00Z"));
    System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse("2010-04-05T17:16:00Z"));

will correctly print out 'Mon Apr 05 13:16:00 EDT 2010'


The 'X' only works if partial seconds are not present: i.e. SimpleDateFormat pattern of

"yyyy-MM-dd'T'HH:mm:ssX"

Will correctly parse

"2008-01-31T00:00:00Z"

but

"yyyy-MM-dd'T'HH:mm:ss.SX"

Will NOT parse

"2008-01-31T00:00:00.000Z"

Sad but true, a date-time with partial seconds does not appear to be a valid ISO date: http://en.wikipedia.org/wiki/ISO_8601


The time zone should be something like "GMT+00:00" or 0000 in order to be properly parsed by the SimpleDateFormat - you can replace Z with this construction.


The restlet project includes an InternetDateFormat class that can parse RFC 3339 dates.

Restlet InternetDateFormat

Though, you might just want to replace the trailing 'Z' with "UTC" before you parse it.


I provide another answer that I found by api-client-library by Google

try {
    DateTime dateTime = DateTime.parseRfc3339(date);
    dateTime = new DateTime(new Date(dateTime.getValue()), TimeZone.getDefault());
    long timestamp = dateTime.getValue();  // get date in timestamp
    int timeZone = dateTime.getTimeZoneShift();  // get timezone offset
} catch (NumberFormatException e) {
    e.printStackTrace();
}

Installation guide,
https://developers.google.com/api-client-library/java/google-api-java-client/setup#download

Here is API reference,
https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/util/DateTime

Source code of DateTime Class,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/main/java/com/google/api/client/util/DateTime.java

DateTime unit tests,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/test/java/com/google/api/client/util/DateTimeTest.java#L121


With regards to JSR-310 another project of interest might be threetenbp.

JSR-310 provides a new date and time library for Java SE 8. This project is the backport to Java SE 6 and 7.

In case you are working on an Android project you might want to checkout the ThreeTenABP library.

compile "com.jakewharton.threetenabp:threetenabp:${version}"

JSR-310 was included in Java 8 as the java.time.* package. It is a full replacement for the ailing Date and Calendar APIs in both Java and Android. JSR-310 was backported to Java 6 by its creator, Stephen Colebourne, from which this library is adapted.


Under Java 8 use the predefined DateTimeFormatter.ISO_DATE_TIME

 DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
 ZonedDateTime result = ZonedDateTime.parse("2010-04-05T17:16:00Z", formatter);

I guess its the easiest way


Since java 8 just use ZonedDateTime.parse("2010-04-05T17:16:00Z")

참고URL : https://stackoverflow.com/questions/2580925/simpledateformat-parsing-date-with-z-literal

반응형