ISO 8601 형식의 문자열을 로 변환하려고 합니다 java.util.Date
.
yyyy-MM-dd'T'HH:mm:ssZ
로케일 (샘플 비교)과 함께 사용 하면 패턴 이 ISO8601을 준수한다는 것을 알았습니다 .
그러나를 사용하면 java.text.SimpleDateFormat
올바른 형식의 String을 변환 할 수 없습니다 2010-01-01T12:00:00+01:00
. 2010-01-01T12:00:00+0100
콜론없이 먼저로 변환해야 합니다.
현재 솔루션은
SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.GERMANY);
String date = "2010-01-01T12:00:00+01:00".replaceAll("\\+0([0-9]){1}\\:00", "+0$100");
System.out.println(ISO8601DATEFORMAT.parse(date));
분명히 그렇게 좋지 않습니다. 내가 누락되었거나 더 나은 해결책이 있습니까?
대답
JuanZe의 의견 덕분에 Joda-Time 마술을 발견했으며 여기에도 설명되어 있습니다 .
그래서 해결책은
DateTimeFormatter parser2 = ISODateTimeFormat.dateTimeNoMillis();
String jtdate = "2010-01-01T12:00:00+01:00";
System.out.println(parser2.parseDateTime(jtdate));
또는 간단히 말하면 생성자를 통해 기본 파서를 사용하십시오.
DateTime dt = new DateTime( "2010-01-01T12:00:00+01:00" ) ;
나에게 이것은 좋다.
답변
불행히도 SimpleDateFormat (Java 6 이하)에 사용 가능한 시간대 형식 은 ISO 8601을 준수 하지 않습니다 . SimpleDateFormat은 “GMT + 01 : 00″또는 “+0100″과 같은 시간대 문자열을 이해하며 RFC # 822 에 따른 문자열 입니다.
Java 7이 ISO 8601에 따라 시간대 디스크립터에 대한 지원을 추가하더라도 SimpleDateFormat은 선택적 파트를 지원하지 않으므로 완전한 날짜 문자열을 올바르게 구문 분석 할 수 없습니다.
regexp를 사용하여 입력 문자열을 다시 포맷하는 것은 분명히 하나의 가능성이지만 대체 규칙은 질문처럼 간단하지 않습니다.
- 일부 시간대는 UTC 이외의 정규 시간이 아니므로 문자열이 반드시 “: 00″으로 끝나는 것은 아닙니다.
- ISO8601은 시간대에 포함 된 시간 만 허용하므로 “+01″은 “+01 : 00″과 같습니다.
- ISO8601에서는 “Z”를 사용하여 “+00 : 00″대신 UTC를 나타낼 수 있습니다.
JAXB가 XML 스키마 스펙에 따라 ISO8601 날짜 문자열을 구문 분석 할 수 있어야하므로 더 쉬운 솔루션은 JAXB에서 데이터 유형 변환기를 사용하는 것입니다. 객체 javax.xml.bind.DatatypeConverter.parseDateTime("2010-01-01T12:00:00Z")
를 제공하고 Calendar
객체가 필요한 경우 getTime ()을 사용할 수 있습니다 Date
.
아마도 Joda-Time 을 사용할 수도 있지만 왜 그렇게 신경 써야할지 모르겠습니다.
답변
DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String string1 = "2001-07-04T12:08:56.235-0700";
Date result1 = df1.parse(string1);
DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
String string2 = "2001-07-04T12:08:56.235-07:00";
Date result2 = df2.parse(string2);
당신은 섹션에서 더 많은 예제를 찾을 수 있습니다 예 에서 SimpleDateFormat에의 javadoc는 .
UPD 02/13/2020 : Java 8에서이를 수행 하는 완전히 새로운 방법 이 있습니다
답변
좋아,이 질문에 이미 답변되었지만 어쨌든 내 답변을 삭제하겠습니다. 누군가를 도울 수 있습니다.
Android (API 7) 솔루션을 찾고 있습니다.
- Joda는 의문의 여지가 없었습니다-그것은 거대하고 초기화가 느려집니다. 또한 특정 목적을 위해 큰 과잉으로 보였다.
- 관련 답변은
javax.xml
Android API 7에서 작동하지 않습니다.
이 간단한 클래스를 구현했습니다. 가장 일반적인 형식 의 ISO 8601 문자열 만 다루지 만 경우에 따라 충분해야합니다 (입력 형식 이 확실 할 경우 ).
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* Helper class for handling a most common subset of ISO 8601 strings
* (in the following format: "2008-03-01T13:00:00+01:00"). It supports
* parsing the "Z" timezone, but many other less-used features are
* missing.
*/
public final class ISO8601 {
/** Transform Calendar to ISO 8601 string. */
public static String fromCalendar(final Calendar calendar) {
Date date = calendar.getTime();
String formatted = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.format(date);
return formatted.substring(0, 22) + ":" + formatted.substring(22);
}
/** Get current date and time formatted as ISO 8601 string. */
public static String now() {
return fromCalendar(GregorianCalendar.getInstance());
}
/** Transform ISO 8601 string to Calendar. */
public static Calendar toCalendar(final String iso8601string)
throws ParseException {
Calendar calendar = GregorianCalendar.getInstance();
String s = iso8601string.replace("Z", "+00:00");
try {
s = s.substring(0, 22) + s.substring(23); // to get rid of the ":"
} catch (IndexOutOfBoundsException e) {
throw new ParseException("Invalid length", 0);
}
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(s);
calendar.setTime(date);
return calendar;
}
}
성능 참고 사항 : Android 2.1 의 버그 를 피하기 위해 매번 새로운 SimpleDateFormat을 인스턴스화 합니다. 내가 그랬던 것처럼 이 수수께끼를보십시오 . 다른 Java 엔진의 경우 스레드를 안전하게하기 위해 ThreadLocal을 사용하여 개인 정적 필드에 인스턴스를 캐시 할 수 있습니다.
답변
java.time
java.time의 API (나중에 자바 8에 내장)를 좀 더 쉽게이 있습니다.
마지막에 (Zulu 의 경우와 같이) 입력이 UTC 이면 클래스를 구문 분석 할 수 있습니다.Z
Instant
java.util.Date date = Date.from( Instant.parse( "2014-12-12T10:39:40Z" ));
입력이 끝에 (Zulu)로 표시된 UTC 가 아닌 다른 UTC에서 오프셋 값일 수있는 경우 클래스를 사용하여 구문 분석하십시오.Z
OffsetDateTime
OffsetDateTime odt = OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" );
그런 다음을 추출하고을 호출 Instant
하여 java.util.Date
으로 변환하십시오 from
.
Instant instant = odt.toInstant(); // Instant is always in UTC.
java.util.Date date = java.util.Date.from( instant );
답변
잭슨 데이터 바인딩 라이브러리는 또한이 ISO8601DateFormat 클래스 에서 그 (실제 구현하지 ISO8601Utils을 .
ISO8601DateFormat df = new ISO8601DateFormat();
Date d = df.parse("2010-07-28T22:25:51Z");
답변
tl; dr
OffsetDateTime.parse ( "2010-01-01T12:00:00+01:00" )
java.time 사용
Java 8 이상의 새로운 java.time 패키지는 Joda-Time에서 영감을 받았습니다.
OffsetDateTime
클래스는 함께 타임 라인에 잠시 나타냅니다 부터 UTC 오프셋 이 아닌 시간대를.
OffsetDateTime odt = OffsetDateTime.parse ( "2010-01-01T12:00:00+01:00" );
호출 toString
하면 표준 ISO 8601 형식으로 문자열이 생성됩니다.
2010-01-01T12 : 00 + 01 : 00
UTC 렌즈를 통해 동일한 값을 보려면를 추출 Instant
하거나 오프셋을에서 +01:00
로 조정하십시오 00:00
.
Instant instant = odt.toInstant();
…또는…
OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC );
원하는 경우 시간대를 조정하십시오. 시간대 의 역사 오프셋로부터 – UTC 예컨대 일광 절약 시간 (DST) 등의 변형을 처리하는 일련의 규칙으로, 영역에 대한 값. 따라서 가능할 때마다 단순한 오프셋이 아닌 시간대를 적용하십시오.
ZonedDateTime zonedDateTimeMontréal = odt.atZoneSameInstant( ZoneId.of( "America/Montreal" ) );
java.time에 대하여
java.time의 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이 클래스는 까다로운 기존에 대신 기존 과 같은 날짜 – 시간의 수업을 java.util.Date
, Calendar
, SimpleDateFormat
.
Joda 타임 프로젝트는 지금에 유지 관리 모드 의로 마이그레이션을 조언 java.time의 클래스.
자세한 내용은 Oracle Tutorial을 참조하십시오 . 많은 예제와 설명을 보려면 스택 오버플로를 검색하십시오. 사양은 JSR 310 입니다.
java.time 객체를 데이터베이스와 직접 교환 할 수 있습니다 . JDBC 4.2 이상을 준수 하는 JDBC 드라이버를 사용하십시오 . 문자열이 필요없고 수업이 필요 없습니다 .java.sql.*
java.time 클래스는 어디서 구할 수 있습니까?
- 자바 SE 8 , 자바 SE 9 , 자바 SE (10) , 그리고 나중에
- 내장.
- 번들로 구현 된 표준 Java API의 일부입니다.
- Java 9에는 몇 가지 사소한 기능과 수정 사항이 추가되었습니다.
- Java SE 6 및 Java SE 7
- 대부분의 java.time 기능은 ThreeTen-Backport의 Java 6 & 7로 백 포트됩니다 .
- 기계적 인조 인간
- java.time 클래스의 최신 버전의 Android 번들 구현.
- 이전 Android (<26)의 경우 ThreeTenABP 프로젝트 는 위에서 언급 한 ThreeTen-Backport를 채택합니다 . ThreeTenABP 사용 방법…을 참조하십시오 .
ThreeTen – 추가 프로젝트 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 향후 java.time에 추가 될 수있는 입증 된 근거입니다. 당신은 여기에 몇 가지 유용한 클래스와 같은 찾을 수 있습니다 Interval
, YearWeek
, YearQuarter
, 그리고 더 .
답변
Java 버전 7의 경우
http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html Oracle 문서를 따를 수 있습니다.
X-ISO 8601 시간대에 사용
TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());
System.out.println(nowAsISO);
DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
//nowAsISO = "2013-05-31T00:00:00Z";
Date finalResult = df1.parse(nowAsISO);
System.out.println(finalResult);