ISO 8601 호환 문자열을 java.util로 변환하는 중.날짜
ISO 8601 형식 문자열을java.util.Date
.
나는 그 패턴을 찾았다.yyyy-MM-dd'T'HH:mm:ssZ
로케일과 함께 사용할 경우 ISO8601 준수 여부(표본 비교).
그러나, 사용java.text.SimpleDateFormat
올바른 형식의 문자열을 변환할 수 없는 경우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은 RFC # 822에 따라 "GMT+01:00" 또는 "+0100"과 같은 시간대 문자열을 이해한다.
자바 7이 ISO 8601에 따라 시간대 설명자에 대한 지원을 추가했더라도 SimpleDateFormat은 선택적 부품에 대한 지원이 없어 여전히 완전한 날짜 문자열을 제대로 구문 분석할 수 없다.
regexp를 사용하여 입력 문자열을 다시 포맷하는 것은 물론 한 가지 가능성이 있지만, 대체 규칙은 질문에서처럼 간단하지 않다.
- 일부 시간대는 UTC를 완전히 사용하지 않는 시간이므로 문자열이 반드시 ":00"으로 끝나는 것은 아니다.
- ISO8601은 시간대에 포함되는 시간만 허용하므로 "+01"은 "+01:00"과 같다.
- ISO8601은 "+00:00" 대신 "Z"를 사용하여 UTC를 나타낼 수 있다.
JAXB는 XML 스키마 사양에 따라 ISO8601 날짜 문자열을 구문 분석할 수 있어야 하기 때문에 더 쉬운 솔루션은 JAXB의 데이터 유형 변환기를 사용하는 것이다. javax.xml.bind.DatatypeConverter.parseDateTime("2010-01-01T12:00:00Z")
A을 줄 것이다.Calendar
객체에 getTime()을 간단히 사용할 수 있으며, 필요한 경우Date
이의를 제기하다
조다 타임도 쓸 수 있을 텐데 왜 그런 걸 신경써야 하는지 모르겠어.
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:자바 8에서 이것을 하는 완전히 새로운 방법이 있다.
좋아, 이 질문은 이미 답은 나왔지만, 어쨌든 답은 그만둘게.누군가에게 도움이 될 수도 있다.
안드로이드(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;
}
}
성능 노트:나는 안드로이드 2.1의 버그를 피하기 위해 매번 새로운 SimpleDateFormat을 인스턴스화한다.나만큼 놀랐다면 이 수수께끼를 보라.다른 Java 엔진의 경우, 전용 정적 필드(스레드 로컬 사용, 스레드 안전)에서 인스턴스를 캐시할 수 있다.
자바.시간
Java.time API(Java 8 이상에 구축됨)는 이것을 조금 더 쉽게 한다.
입력이 UTC에 있는 것을 알고 있는 경우(예:Z
(줄루에게) 마지막에, 학급은 파스를 낼 수 있다.
java.util.Date date = Date.from( Instant.parse( "2014-12-12T10:39:40Z" ));
만약 당신의 입력이 UTC가 아닌 UTC로부터의 또 다른 오프셋 값일 수 있다면Z
(줄루) 마지막에 반을 이용해서 구문 분석한다.
OffsetDateTime odt = OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" );
그런 다음 , 를 추출하고, 부름으로써 로 변환한다.
Instant instant = odt.toInstant(); // Instant is always in UTC.
java.util.Date date = java.util.Date.from( instant );
tl;dr
OffsetDateTime.parse ( "2010-01-01T12:00:00+01:00" )
java.time 사용
Java 8 이상에 있는 새로운 Java.time 패키지는 Joda-time에서 영감을 받았다.
그OffsetDateTime
class는 시간 표시 막대에서 오프셋-From-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 );
원하는 경우 표준 시간대로 조정하십시오.표준 시간대는 일광 절약 시간(DST)과 같은 이상 현상을 처리하기 위한 일련의 규칙을 가진 지역의 UTC 오프셋부터의 기록이다.따라서 가능하면 항상 단순한 간격띄우기보다는 표준 시간대를 적용하십시오.
ZonedDateTime zonedDateTimeMontréal = odt.atZoneSameInstant( ZoneId.of( "America/Montreal" ) );
날짜 전용 값으로 를 사용하십시오.
LocalDate ld = LocalDate.of( 2010 , Month.JANUARY , 1 ) ;
또는:
LocalDate ld = LocalDate.parse( "2010-01-01" ) ;
java.time 정보
자바.시간 프레임워크는 Java 8 이상에 내장되어 있다.이러한 수업은 , , & 같은 골치 아픈 오래된 레거시 날짜-시간 수업을 대체한다.
자세한 내용은 Oracle 자습서를 참조하십시오.그리고 스택 오버플로를 검색하여 많은 예와 설명을 참조하십시오.사양은 JSR 310이다.
현재 유지보수 모드에 있는 조다 타임 프로젝트는 Java.time 클래스로의 마이그레이션을 권고한다.
Java.time 객체를 데이터베이스와 직접 교환할 수 있다.JDBC 4.2 이상과 호환되는 JDBC 드라이버를 사용하십시오.끈이 필요 없고, 끈이 필요 없다.java.sql.*
반최대 절전 모드 5 & JPA 2.2는 Java.time을 지원한다.
Java.time 클래스를 가져올 위치
- 자바 SE 8, 자바 SE 9, 자바 SE 10, 자바 SE 11 및 이후 버전 - 번들 구현이 포함된 표준 Java API의 일부.
- 자바 9는 몇 가지 사소한 특징과 수정 사항을 가지고 왔다.
- Java SE 6 및 자바 SE 7
- 대부분의 Java.time 기능은 스리텐 백포트에서 Java 6 & 7로 백포트된다.
- 안드로이드
- 이후 버전의 Android(26+) 번들 구현 Java.time 클래스.
- 이전의 Android (<26)의 경우, API 분리의 프로세스는 Android에 원래 내장되어 있지 않은 Java.time 기능의 하위 집합을 가져온다.
- 디제게어링이 필요한 것을 제공하지 않으면, 스리텐ABP 프로젝트는 스리텐 백포트(위에서 언급함)를 안드로이드에 적응시킨다.ThreeTenABP 사용 방법을 참조하십시오.
Jackson-Databind 라이브러리에는 이를 수행하는 ISO8601DateFormat 클래스도 있다(ISO8601Utils의 실제 구현).
ISO8601DateFormat df = new ISO8601DateFormat();
Date d = df.parse("2010-07-28T22:25:51Z");
Java 8에서 시작하여 다음과 같이 완전히 공식적으로 지원되는 방법이 있다.
String s = "2020-02-13T18:51:09.840Z";
TemporalAccessor ta = DateTimeFormatter.ISO_INSTANT.parse(s);
Instant i = Instant.from(ta);
Date d = Date.from(i);
Java 버전 7의 경우
오라클 문서를 참조하십시오. http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
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);
DatatypeConverter 솔루션은 일부 VM에서 작동하지 않음내게는 다음과 같은 것이 통한다.
javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar("2011-01-01Z").toGregorianCalendar().getTime()
Joda는 박스에서 작동하지 않는다는 것을 알게 되었다(특히 내가 위에서 날짜에 시간대를 두고 제공한 예시, 유효해야 함)
나는 우리가 사용해야 한다고 생각한다.
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
날짜로2010-01-01T12:00:00Z
ISO8601 타임스탬프를 구문 분석하는 또 다른 매우 간단한 방법은org.apache.commons.lang.time.DateUtils
:
import static org.junit.Assert.assertEquals;
import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang.time.DateUtils;
import org.junit.Test;
public class ISO8601TimestampFormatTest {
@Test
public void parse() throws ParseException {
Date date = DateUtils.parseDate("2010-01-01T12:00:00+01:00", new String[]{ "yyyy-MM-dd'T'HH:mm:ssZZ" });
assertEquals("Fri Jan 01 12:00:00 CET 2010", date.toString());
}
}
Java 7+에 대한 해결 방법은 SimpleDateFormat:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);
이 코드는 다음과 같이 ISO8601 형식을 구문 분석할 수 있다.
2017-05-17T06:01:43.785Z
2017-05-13T02:58:21.391+01:00
하지만 자바6에서는SimpleDateFormat
이해하지 못하다X
과 의기를 이다.
IllegalArgumentException: Unknown pattern character 'X'
우리는 ISO8601 날짜를 Java 6에서 읽을 수 있는 형식으로 표준화해야 한다.SimpleDateFormat
.
public static Date iso8601Format(String formattedDate) throws ParseException {
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);
return df.parse(formattedDate);
} catch (IllegalArgumentException ex) {
// error happen in Java 6: Unknown pattern character 'X'
if (formattedDate.endsWith("Z")) formattedDate = formattedDate.replace("Z", "+0000");
else formattedDate = formattedDate.replaceAll("([+-]\\d\\d):(\\d\\d)\\s*$", "$1$2");
DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
return df1.parse(formattedDate);
}
}
위의 방법에서 [을(를) 교체하십시오.Z
와 함께+0000
] 또는 [+01:00
와 함께+0100
했을 때할 수 Java 6에 가서 try/catch를 if 문장으로 하면 Java 6에서 try/catchda.
ISO8601을 현재까지 변환하기 위해 많은 것을 검색한 후, 갑자기 ISO8601Util.java라는 자바 클래스를 찾았고, 이것은 com.gso.gson.internal.bind.util의 일부였다.그래서 날짜를 변환하는 데 사용할 수 있다.
ISO8601Utils.parse("2010-01-01T12:00:00Z" , ParsePosition(0))
그리고 당신은 간단히 이 코틀린 확장 기능을 사용할 수 있다.
fun String.getDateFromString() : Date? = ISO8601Utils.parse(this ,
ParsePosition(0))
자바 8+
답변에서 찾지 못한 간단한 라이너 하나:
Date date = Date.from(ZonedDateTime.parse("2010-01-01T12:00:00+01:00").toInstant());
날짜에 시간대가 포함되어 있지 않고 UTC에 저장되지만 간단한 출력 중에도 JVM 시간대로 적절하게 변환됨System.out.println(date)
.
자바.시간
Java 8에서는 Java.time을 사용할 수 있다는 점에 유의하십시오.ZonedDateTime 클래스 및 해당 정적parse(CharSequence text)
방법
나는 같은 문제에 직면했고 다음 코드로 그것을 해결했다.
public static Calendar getCalendarFromISO(String datestring) {
Calendar calendar = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault()) ;
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
try {
Date date = dateformat.parse(datestring);
date.setHours(date.getHours() - 1);
calendar.setTime(date);
String test = dateformat.format(calendar.getTime());
Log.e("TEST_TIME", test);
} catch (ParseException e) {
e.printStackTrace();
}
return calendar;
}
아까 내가 사용했었는데SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault());
그러나 나중에 나는 그 예외의 주된 원인이 그 예외에 있다는 것을 알았다.yyyy-MM-dd'T'HH:mm:ss.SSSZ
그래서 사용했다.
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
그것은 나에게 잘 먹혔다.
Java는 여기의 훌륭한 답변이 증명하듯이 날짜/시간을 구문 분석할 수 있는 십여 가지의 다른 방법을 가지고 있다.하지만 다소 놀랍게도, 어떤 자바 시간 클래스도 ISO 8601을 완전히 구현하지 않는다!
Java 8의 경우 다음 사항을 권장한다.
ZonedDateTime zp = ZonedDateTime.parse(string);
Date date = Date.from(zp.toInstant());
그것은 "2017-09-13T10:36:40Z" 또는 "2017-09-13T10:36:40+01:00"과 같은 UTC의 예와 오프셋을 모두 처리할 것이다.그것은 대부분의 사용 사례에 적합하다.
그러나 유효한 ISO 8601 날짜 시간인 "2017-09-13T10:36:40+01"과 같은 예는 다루지 않을 것이다.
또한 "2017-09-13"과 같은 날짜만 처리하지는 않을 것이다.
만약 네가 그것들을 처리해야 한다면, 나는 먼저 구문 냄새를 맡기 위해 regex를 사용하는 것을 제안하고 싶다.
여기에는 많은 코너 사례와 함께 ISO 8601의 멋진 목록이 있다: https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/ 나는 이 모든 사례를 다룰 수 있는 Java 클래스에 대해 잘 모른다.
또한 다음 클래스를 사용할 수 있다.
org.springframework.extensions.surf.util.ISO8601DateFormat
Date date = ISO8601DateFormat.parse("date in iso8601");
Java Doc - Package org.springframework.extension.surf.maven에 연결하십시오.plugin.util
다른 사람들이 언급했듯이, Android는 SDK에 포함된 클래스를 사용하여 ISO 8601 날짜의 구문 분석/포맷을 지원하는 좋은 방법이 없다.나는 이 코드를 여러 번 썼기 때문에 마침내 ISO 8601과 RFC 1123 날짜의 포맷과 구문을 지원하는 DateUtils 클래스를 포함하는 Gist를 만들었다.또한 Gest는 자신이 무엇을 지원하는지를 보여주는 테스트 케이스를 포함하고 있다.
https://gist.github.com/mraccola/702330625fad8eebe7d3
SimpleDateFormat for JAVA 1.7은 ISO 8601 포맷을 위한 멋진 패턴을 가지고 있다.
내가 한 일은 다음과 같다.
Date d = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
Locale.ENGLISH).format(System.currentTimeMillis());
문자열을 다음과 같이 사용하십시오.LocalDate.parse(((String) data.get("d_iso8601")),DateTimeFormatter.ISO_DATE)
단 하나의 자바 라이브러리도 https://en.wikipedia.org/wiki/ISO_8601에서처럼 ISO 8601의 모든 날짜 형식을 지원하지 않는다는 사실에 놀랐다.Joda DateTime은 그들 대부분을 지원하고 있었지만 전부는 아니었고 그래서 나는 모든 것을 처리하기 위해 맞춤 논리를 추가했다.이것이 나의 실행이다.
import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang3.time.DateUtils;
import org.joda.time.DateTime;
public class ISO8601DateUtils {
/**
* It parses all the date time formats from https://en.wikipedia.org/wiki/ISO_8601 and returns Joda DateTime.
* Zoda DateTime does not support dates of format 20190531T160233Z, and hence added custom logic to handle this using SimpleDateFormat.
* @param dateTimeString ISO 8601 date time string
* @return
*/
public static DateTime parse(String dateTimeString) {
try {
return new DateTime( dateTimeString );
} catch(Exception e) {
try {
Date dateTime = DateUtils.parseDate(dateTimeString, JODA_NOT_SUPPORTED_ISO_DATES);
return new DateTime(dateTime.getTime());
} catch (ParseException e1) {
throw new RuntimeException(String.format("Date %s could not be parsed to ISO date", dateTimeString));
}
}
}
private static String[] JODA_NOT_SUPPORTED_ISO_DATES = new String[] {
// upto millis
"yyyyMMdd'T'HHmmssSSS'Z'",
"yyyyMMdd'T'HHmmssSSSZ",
"yyyyMMdd'T'HHmmssSSSXXX",
"yyyy-MM-dd'T'HHmmssSSS'Z'",
"yyyy-MM-dd'T'HHmmssSSSZ",
"yyyy-MM-dd'T'HHmmssSSSXXX",
// upto seconds
"yyyyMMdd'T'HHmmss'Z'",
"yyyyMMdd'T'HHmmssZ",
"yyyyMMdd'T'HHmmssXXX",
"yyyy-MM-dd'T'HHmmss'Z'",
"yyyy-MM-dd'T'HHmmssZ",
"yyyy-MM-dd'T'HHmmssXXX",
// upto minutes
"yyyyMMdd'T'HHmm'Z'",
"yyyyMMdd'T'HHmmZ",
"yyyyMMdd'T'HHmmXXX",
"yyyy-MM-dd'T'HHmm'Z'",
"yyyy-MM-dd'T'HHmmZ",
"yyyy-MM-dd'T'HHmmXXX",
//upto hours is already supported by Joda DateTime
};
}
다음과 같이 하십시오.
public static void main(String[] args) throws ParseException {
String dateStr = "2016-10-19T14:15:36+08:00";
Date date = javax.xml.bind.DatatypeConverter.parseDateTime(dateStr).getTime();
System.out.println(date);
}
출력 내용은 다음과 같다.
2016년 10월 19일 수요일 15:15:36 CST
ISO8601에서 날짜를 구문 분석하는 방법과 LocalDateTime에서 DST를 처리하지 않는 방법을 보여주는 작은 테스트.
@Test
public void shouldHandleDaylightSavingTimes() throws ParseException {
//ISO8601 UTC date format
SimpleDateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
// 1 hour of difference between 2 dates in UTC happening at the Daylight Saving Time
Date d1 = utcFormat.parse("2019-10-27T00:30:00.000Z");
Date d2 = utcFormat.parse("2019-10-27T01:30:00.000Z");
//Date 2 is before date 2
Assert.assertTrue(d1.getTime() < d2.getTime());
// And there is 1 hour difference between the 2 dates
Assert.assertEquals(1000*60*60, d2.getTime() - d1.getTime());
//Print the dates in local time
SimpleDateFormat localFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm z Z", Locale.forLanguageTag("fr_CH"));
localFormat.setTimeZone(TimeZone.getTimeZone("Europe/Zurich"));
//Both dates are at 02h30 local time (because of DST), but one is CEST +0200 and the other CET +0100 (clock goes backwards)
Assert.assertEquals("2019-10-27 02:30 CEST +0200", localFormat.format(d1));
Assert.assertEquals("2019-10-27 02:30 CET +0100", localFormat.format(d2));
//Small test that shows that LocalDateTime does not handle DST (and should not be used for storing timeseries data)
LocalDateTime ld1 = LocalDateTime.ofInstant(d1.toInstant(), ZoneId.of("Europe/Zurich"));
LocalDateTime ld2 = LocalDateTime.ofInstant(d2.toInstant(), ZoneId.of("Europe/Zurich"));
//Note that a localdatetime does not handle DST, therefore the 2 dates are the same
Assert.assertEquals(ld1, ld2);
//They both have the following local values
Assert.assertEquals(2019, ld1.getYear());
Assert.assertEquals(27, ld1.getDayOfMonth());
Assert.assertEquals(10, ld1.getMonthValue());
Assert.assertEquals(2, ld1.getHour());
Assert.assertEquals(30, ld1.getMinute());
Assert.assertEquals(0, ld1.getSecond());
}
UTC에서 원하는 형식으로 변환하려는 경우.우리가 머무는 지역/장소에 따라 달라질 것이다.
//utcDate = "2021-06-05T02:46:29Z"
fun converterUtcToReadableDateTime(utcDate: String): String {
val offsetDateTime = OffsetDateTime.ofInstant(Instant.parse(utcDate), ZoneId.systemDefault())
val patternDate = "dd MMM yyyy h:mm a"
return DateTimeFormatter.ofPattern(patternDate).format(offsetDateTime)
}
fun converterUtcToReadableDate(utcDate: String): String {
val offsetDateTime = OffsetDateTime.ofInstant(Instant.parse(utcDate), ZoneId.systemDefault())
val patternDate = "d MMM yyyy"
return DateTimeFormatter.ofPattern(patternDate).format(offsetDateTime)
}
fun converterUtcToReadableTime(utcDate: String): String {
val offsetDateTime = OffsetDateTime.ofInstant(Instant.parse(utcDate), ZoneId.systemDefault())
val patternDate = "h:mm a"
return DateTimeFormatter.ofPattern(patternDate).format(offsetDateTime)
}
나도 비슷한 요구가 있었다.나는 정확한 포맷을 미리 알지 못한 채 ISO8601을 준수하는 어떤 날짜라도 구문 분석할 수 있어야 했고, 안드로이드에서도 작동할 수 있는 가벼운 솔루션을 원했다.
내가 내 니즈를 검색했을 때 나는 이 질문을 우연히 발견했고, AFAIU는 내 니즈에 완전히 맞는 답이 없다는 것을 알아차렸다.그래서 나는 jISO8601을 개발하여 maven central에 밀어넣었다.
그냥 네 안에 추가해.pom.xml
:
<dependency>
<groupId>fr.turri</groupId>
<artifactId>jISO8601</artifactId>
<version>0.2</version>
</dependency>
그럼 가봐
import fr.turri.jiso8601.*;
...
Calendar cal = Iso8601Deserializer.toCalendar("1985-03-04");
Date date = Iso8601Deserializer.toDate("1985-03-04T12:34:56Z");
도움이 되길 바래.
이런 날짜만 포맷하면 Java 6 기반 응용 프로그램에서 다음과 같은 기능이 작동했다.라는 것이 있다.DateFormat
계급JacksonThymeleafISO8601DateFormat
사라진 결장을 삽입하는 백리향 프로젝트:
나는 그것을 ECMAScript 날짜 형식 호환성에 사용했다.
기본 기능 제공: @wrygiel.
이 함수는 ISO8601 형식을 오프셋 값을 처리할 수 있는 자바 날짜로 변환할 수 있다.ISO 8601의 정의에 따라 오프셋은 다른 형식으로 언급될 수 있다.
±[hh]:[mm]
±[hh][mm]
±[hh]
Eg: "18:30Z", "22:30+04", "1130-0700", and "15:00-03:30" all mean the same time. - 06:30PM UTC
이 클래스는 변환하는 정적 메서드가 있음
- ISO8601 문자열을 날짜(로컬 타임존) 개체로
- ISO8601 문자열까지의 날짜
- 일광 절약은 자동으로 계산됨
샘플 ISO8601 문자열
/* "2013-06-25T14:00:00Z";
"2013-06-25T140000Z";
"2013-06-25T14:00:00+04";
"2013-06-25T14:00:00+0400";
"2013-06-25T140000+0400";
"2013-06-25T14:00:00-04";
"2013-06-25T14:00:00-0400";
"2013-06-25T140000-0400";*/
public class ISO8601DateFormatter {
private static final DateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
private static final DateFormat DATE_FORMAT_2 = new SimpleDateFormat("yyyy-MM-dd'T'HHmmssZ");
private static final String UTC_PLUS = "+";
private static final String UTC_MINUS = "-";
public static Date toDate(String iso8601string) throws ParseException {
iso8601string = iso8601string.trim();
if(iso8601string.toUpperCase().indexOf("Z")>0){
iso8601string = iso8601string.toUpperCase().replace("Z", "+0000");
}else if(((iso8601string.indexOf(UTC_PLUS))>0)){
iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_PLUS));
iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_PLUS), UTC_PLUS);
}else if(((iso8601string.indexOf(UTC_MINUS))>0)){
iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_MINUS));
iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_MINUS), UTC_MINUS);
}
Date date = null;
if(iso8601string.contains(":"))
date = DATE_FORMAT_1.parse(iso8601string);
else{
date = DATE_FORMAT_2.parse(iso8601string);
}
return date;
}
public static String toISO8601String(Date date){
return DATE_FORMAT_1.format(date);
}
private static String replaceColon(String sourceStr, int offsetIndex){
if(sourceStr.substring(offsetIndex).contains(":"))
return sourceStr.substring(0, offsetIndex) + sourceStr.substring(offsetIndex).replace(":", "");
return sourceStr;
}
private static String appendZeros(String sourceStr, int offsetIndex, String offsetChar){
if((sourceStr.length()-1)-sourceStr.indexOf(offsetChar,offsetIndex)<=2)
return sourceStr + "00";
return sourceStr;
}
}
많은 사람들이 원하는 것은 JSON 데이트 문자열을 파싱하는 것이라고 생각한다.이 페이지에 오면 JavaScript JSON 날짜를 Java 날짜로 변환할 가능성이 있다.
JSON 날짜 문자열의 모양을 표시하려면:
var d=new Date();
var s = JSON.stringify(d);
document.write(s);
document.write("<br />"+d);
"2013-12-14T01:55:33.412Z"
Fri Dec 13 2013 17:55:33 GMT-0800 (PST)
JSON 날짜 문자열은 2013-12-14T01:55:33.412Z이다.
날짜는 말 당 JSON 규격으로 다루지 않지만, 위의 내용은 매우 구체적인 ISO 8601 형식인 반면, ISO_8601은 훨씬 더 크고 매우 중요한 형식임에도 불구하고 하위 집합에 불과하다.
http://www.json.org 참조 http://www.json.org 참조 http://www.w3.org/TR/NOTE-datetime 참조
마침 나는 JSON 파서와 PLIST 파서를 썼는데, 둘 다 ISO-8601을 사용하지만 동일한 비트는 사용하지 않는다.
/*
var d=new Date();
var s = JSON.stringify(d);
document.write(s);
document.write("<br />"+d);
"2013-12-14T01:55:33.412Z"
Fri Dec 13 2013 17:55:33 GMT-0800 (PST)
*/
@Test
public void jsonJavaScriptDate() {
String test = "2013-12-14T01:55:33.412Z";
Date date = Dates.fromJsonDate ( test );
Date date2 = Dates.fromJsonDate_ ( test );
assertEquals(date2.toString (), "" + date);
puts (date);
}
나는 내 프로젝트를 위해 이것을 하기 위한 두 가지 방법을 썼다.하나의 표준, 하나의 빠른.
다시 말하지만, JSON 날짜 문자열은 ISO 8601의 매우 구체적인 구현이다....
(다른 하나는 다른 ISO 8601 형식인 PLIST 날짜에 사용할 수 있는 다른 답변에 게시했다.)
JSON 날짜는 다음과 같다.
public static Date fromJsonDate_( String string ) {
try {
return new SimpleDateFormat ( "yyyy-MM-dd'T'HH:mm:ss.SSSXXX").parse ( string );
} catch ( ParseException e ) {
return Exceptions.handle (Date.class, "Not a valid JSON date", e);
}
}
PLIST 파일(ASCII non GNUNext)도 ISO 8601을 사용하지만 밀리초는 없으므로...모든 ISO-8601 날짜가 동일한 것은 아니다.(적어도 나는 아직 밀리스를 사용하는 것과 내가 본 파서는 시간대를 완전히 건너뛰는 것을 찾지 못했다.)
이제 빠른 버전을 위해(Boon에서 찾을 수 있다).
public static Date fromJsonDate( String string ) {
return fromJsonDate ( Reflection.toCharArray ( string ), 0, string.length () );
}
Reflection.to CharArray는 사용 가능한 경우 안전하지 않은 것을 사용하지만 그렇지 않은 경우 기본적으로 문자열.toCharArray로 설정된다는 점에 유의하십시오.
(Reflection.to CharArray ( 문자열 )를 string.to CharArray()로 교체하여 예에서 제외할 수 있다.
public static Date fromJsonDate( char[] charArray, int from, int to ) {
if (isJsonDate ( charArray, from, to )) {
int year = CharScanner.parseIntFromTo ( charArray, from + 0, from + 4 );
int month = CharScanner.parseIntFromTo ( charArray, from +5, from +7 );
int day = CharScanner.parseIntFromTo ( charArray, from +8, from +10 );
int hour = CharScanner.parseIntFromTo ( charArray, from +11, from +13 );
int minute = CharScanner.parseIntFromTo ( charArray, from +14, from +16 );
int second = CharScanner.parseIntFromTo ( charArray, from +17, from +19 );
int miliseconds = CharScanner.parseIntFromTo ( charArray, from +20, from +23 );
TimeZone tz = TimeZone.getTimeZone ( "GMT" );
return toDate ( tz, year, month, day, hour, minute, second, miliseconds );
} else {
return null;
}
}
isJsonDate는 다음과 같이 구현된다.
public static boolean isJsonDate( char[] charArray, int start, int to ) {
boolean valid = true;
final int length = to -start;
if (length != JSON_TIME_LENGTH) {
return false;
}
valid &= (charArray [ start + 19 ] == '.');
if (!valid) {
return false;
}
valid &= (charArray[ start +4 ] == '-') &&
(charArray[ start +7 ] == '-') &&
(charArray[ start +10 ] == 'T') &&
(charArray[ start +13 ] == ':') &&
(charArray[ start +16 ] == ':');
return valid;
}
어쨌든...내 생각엔 여기 오는 사람들이 꽤 많을 것 같아.JSON Date String을 찾고 있을 수 있으며 ISO-8601 날짜이지만 매우 구체적인 구문 분석 작업이 필요한 날짜다.
public static int parseIntFromTo ( char[] digitChars, int offset, int to ) {
int num = digitChars[ offset ] - '0';
if ( ++offset < to ) {
num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
if ( ++offset < to ) {
num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
if ( ++offset < to ) {
num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
if ( ++offset < to ) {
num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
if ( ++offset < to ) {
num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
if ( ++offset < to ) {
num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
if ( ++offset < to ) {
num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
if ( ++offset < to ) {
num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
}
}
}
}
}
}
}
}
return num;
}
자세한 내용은 https://github.com/RichardHightower/boon Boon이 PLIST 파서(ASCII)와 JSON 파서를 가지고 있음을 참조하십시오.
JSON 파서는 내가 아는 자바 JSON 파서 중에서 가장 빠르다.
Gatling Performance Duids에 의해 독립적으로 검증됨.
https://github.com/gatling/json-parsers-benchmark
Benchmark Mode Thr Count Sec Mean Mean error Units
BoonCharArrayBenchmark.roundRobin thrpt 16 10 1 724815,875 54339,825 ops/s
JacksonObjectBenchmark.roundRobin thrpt 16 10 1 580014,875 145097,700 ops/s
JsonSmartBytesBenchmark.roundRobin thrpt 16 10 1 575548,435 64202,618 ops/s
JsonSmartStringBenchmark.roundRobin thrpt 16 10 1 541212,220 45144,815 ops/s
GSONStringBenchmark.roundRobin thrpt 16 10 1 522947,175 65572,427 ops/s
BoonDirectBytesBenchmark.roundRobin thrpt 16 10 1 521528,912 41366,197 ops/s
JacksonASTBenchmark.roundRobin thrpt 16 10 1 512564,205 300704,545 ops/s
GSONReaderBenchmark.roundRobin thrpt 16 10 1 446322,220 41327,496 ops/s
JsonSmartStreamBenchmark.roundRobin thrpt 16 10 1 276399,298 130055,340 ops/s
JsonSmartReaderBenchmark.roundRobin thrpt 16 10 1 86789,825 17690,031 ops/s
스트림, 판독기, 바이트[], char[], CharSequence(StringBuilder, CharacterBuffer) 및 String에 대한 JSON 파서가 가장 빠르다.
더 많은 벤치마크를 보려면 다음을 참조하십시오.
https://github.com/RichardHightower/json-parsers-benchmark
참조URL: https://stackoverflow.com/questions/2201925/converting-iso-8601-compliant-string-to-java-util-date
'programing' 카테고리의 다른 글
Vue 3 마이그레이션 구성 요소의 확장 방법 (0) | 2022.05.07 |
---|---|
이 비즈니스 논리는 Vuex에 얼마나 속하는가? (0) | 2022.05.07 |
Vuex 클래스: Vue 구성 요소 외부의 Vuex 액세스 (0) | 2022.05.07 |
(변수1 % 변수2 == 0) 비효율적인 이유는? (0) | 2022.05.07 |
C의 기본 매개 변수 (0) | 2022.05.07 |