날짜 문자열을 java.util.Date로 구문 분석 할 때 잘못된 패턴 문자 'T'


182

날짜 문자열이 있고 java Date API를 사용하여 일반 날짜로 구문 분석하고 싶습니다. 다음은 내 코드입니다.

public static void main(String[] args) {
    String date="2010-10-02T12:23:23Z";
    String pattern="yyyy-MM-ddThh:mm:ssZ";
    SimpleDateFormat sdf=new SimpleDateFormat(pattern);
    try {
        Date d=sdf.parse(date);
        System.out.println(d.getYear());
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

그러나 예외가 있습니다. java.lang.IllegalArgumentException: Illegal pattern character 'T'

문자열을 분할하고 수동으로 구문 분석 해야하는지 궁금합니다.

BTW, 나는 T의 양쪽에 작은 따옴표 문자를 추가하려고했습니다.

String pattern="yyyy-MM-dd'T'hh:mm:ssZ";

또한 작동하지 않습니다.


1
이 "T"가 무엇을 의미하는지 아십니까? 내가 'T'와 함께 전체 날짜를 날짜로 변환해야한다고 생각하는 한 ( 'Single Quotes'를 통해 건너 뛰지 말고 우리가 빠진 것은 구문 분석 패턴입니다.
coding_idiot

9
T약자 시간 과의 일부입니다 ISO8601 포맷 국제 날짜 시간에 대한 표준입니다.

1
이상하다. T작은 따옴표로 감싸는 것이 나를 위해 일했습니다 (적어도 구문 분석 오류 해결 측면에서).
Agi Hammerthief

답변:


203

Java 8 이상 업데이트

이제 가장 최신 버전의 Java를 Instant.parse("2015-04-28T14:23:38.521Z")사용 Instant하지 않고 사용해야하기 때문에 이제 간단하게 올바른 작업을 수행 할 수 있습니다 java.util.Date.

DateTimeFormatter대신에 사용해야합니다SimpleDateFormatter .

원래 답변 :

아래 설명은 형식이 나타내는 내용으로 여전히 유효합니다. 그러나 Java 8이 어디에나 사용되기 전에 작성되었으므로 Java 8 이상을 사용하는 경우 사용해서는 안되는 이전 클래스를 사용합니다.

이것은 다음과 같이 후행 입력과 함께 작동합니다 Z.

패턴에서 T로 이스케이프' 양쪽에서 .

Z끝에 대한 패턴 은 실제로 XXXJavaDoc에 문서화되어 있으며 SimpleDateFormat실제로 Z는 이전 TimeZone정보 의 마커 이기 때문에 사용 방법에 대해서는 명확하지 않습니다 .

Q2597083.java

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class Q2597083
{
    /**
     * All Dates are normalized to UTC, it is up the client code to convert to the appropriate TimeZone.
     */
    public static final TimeZone UTC;

    /**
     * @see <a href="http://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations">Combined Date and Time Representations</a>
     */
    public static final String ISO_8601_24H_FULL_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";

    /**
     * 0001-01-01T00:00:00.000Z
     */
    public static final Date BEGINNING_OF_TIME;

    /**
     * 292278994-08-17T07:12:55.807Z
     */
    public static final Date END_OF_TIME;

    static
    {
        UTC = TimeZone.getTimeZone("UTC");
        TimeZone.setDefault(UTC);
        final Calendar c = new GregorianCalendar(UTC);
        c.set(1, 0, 1, 0, 0, 0);
        c.set(Calendar.MILLISECOND, 0);
        BEGINNING_OF_TIME = c.getTime();
        c.setTime(new Date(Long.MAX_VALUE));
        END_OF_TIME = c.getTime();
    }

    public static void main(String[] args) throws Exception
    {

        final SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_24H_FULL_FORMAT);
        sdf.setTimeZone(UTC);
        System.out.println("sdf.format(BEGINNING_OF_TIME) = " + sdf.format(BEGINNING_OF_TIME));
        System.out.println("sdf.format(END_OF_TIME) = " + sdf.format(END_OF_TIME));
        System.out.println("sdf.format(new Date()) = " + sdf.format(new Date()));
        System.out.println("sdf.parse(\"2015-04-28T14:23:38.521Z\") = " + sdf.parse("2015-04-28T14:23:38.521Z"));
        System.out.println("sdf.parse(\"0001-01-01T00:00:00.000Z\") = " + sdf.parse("0001-01-01T00:00:00.000Z"));
        System.out.println("sdf.parse(\"292278994-08-17T07:12:55.807Z\") = " + sdf.parse("292278994-08-17T07:12:55.807Z"));
    }
}

다음과 같은 출력을 생성합니다.

sdf.format(BEGINNING_OF_TIME) = 0001-01-01T00:00:00.000Z
sdf.format(END_OF_TIME) = 292278994-08-17T07:12:55.807Z
sdf.format(new Date()) = 2015-04-28T14:38:25.956Z
sdf.parse("2015-04-28T14:23:38.521Z") = Tue Apr 28 14:23:38 UTC 2015
sdf.parse("0001-01-01T00:00:00.000Z") = Sat Jan 01 00:00:00 UTC 1
sdf.parse("292278994-08-17T07:12:55.807Z") = Sun Aug 17 07:12:55 UTC 292278994

26

tl; dr

java.time.Instant클래스를 사용 하여 UTC로 순간을 나타내는 표준 ISO 8601 형식으로 텍스트를 구문 분석 하십시오 .

Instant.parse( "2010-10-02T12:23:23Z" )

ISO 8601

해당 형식은 날짜-시간 문자열 형식에 대한 ISO 8601 표준에 의해 정의됩니다 .

양자 모두:

… 문자열 구문 분석 및 생성에는 기본적으로 ISO 8601 형식을 사용하십시오.

일반적으로 이전 java.util.Date를 사용하지 않아야합니다. /.Calendar & java.text.SimpleDateFormat 클래스 번거롭고 혼란스럽고 결함이 있으므로 . 상호 운용이 필요한 경우 이리저리로 변환 할 수 있습니다.

java.time

Java 8 이상에는 새로운 java.time 프레임 워크 가 내장되어 있습니다. Joda-Time 에서 영감을 얻어 JSR 310 에서 정의 하고 ThreeTen-Extra 프로젝트 에서 확장했습니다 .

Instant instant = Instant.parse( "2010-10-02T12:23:23Z" );  // `Instant` is always in UTC.

이전 클래스로 변환하십시오.

java.util.Date date = java.util.Date.from( instant );  // Pass an `Instant` to the `from` method.

시간대

필요한 경우 시간대를 지정할 수 있습니다.

ZoneId zoneId = ZoneId.of( "America/Montreal" ); // Define a time zone rather than rely implicitly on JVM’s current default time zone.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );  // Assign a time zone adjustment from UTC.

변하게 하다.

java.util.Date date = java.util.Date.from( zdt.toInstant() );  // Extract an `Instant` from the `ZonedDateTime` to pass to the `from` method.

조다 타임

업데이트 : Joda-Time 프로젝트는 현재 유지 보수 모드입니다. 팀은 java.time 으로의 마이그레이션을 조언합니다. 클래스 .

Joda-Time 2.8의 예제 코드는 다음과 같습니다.

org.joda.time.DateTime dateTime_Utc = new DateTime( "2010-10-02T12:23:23Z" , DateTimeZone.UTC );  // Specifying a time zone to apply, rather than implicitly assigning the JVM’s current default.

이전 클래스로 변환하십시오. juDate에는 시간대를 지정할 수 없으므로 지정된 시간대는 변환시 손실됩니다.

java.util.Date date = dateTime_Utc.toDate(); // The `toDate` method converts to old class.

시간대

필요한 경우 시간대를 지정할 수 있습니다.

DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTime_Montreal = dateTime_Utc.withZone ( zone );

최신 및 기존 Java의 날짜-시간 유형 테이블.


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 클래스는 어디서 구할 수 있습니까?

Java 또는 Android 버전에 사용할 java.time 라이브러리의 테이블입니다.

ThreeTen - 추가 프로젝트 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 향후 java.time에 추가 될 수있는 입증 된 근거입니다. 당신은 여기에 몇 가지 유용한 클래스와 같은 찾을 수 있습니다 Interval, YearWeek, YearQuarter, 그리고 .


1
@AalapPatel Joda-Time 프로젝트는 현재 유지 보수 모드에 있습니다. 팀은 java.time 클래스로의 마이그레이션을 권고합니다. 두 사람의 노력은 같은 사람 Stephen Colebourne에 의해 주도됩니다.
Basil Bourque

감사합니다. 서버에서 UTC 시간 및 / 또는 로케일 시간을 반환하여이 시간에 밀리 초를 가져 오는 데 사용합니다.
Aalap Patel

Instant.parse는 안드로이드에서 최소 API 레벨 26이 필요합니다
Naveed Ahmad

1
@NaveedAhmad ThreeTen-BackportThreeTenABP 프로젝트에 대한 답변 맨 아래의 글 머리 기호를 참조하십시오 .
Basil Bourque

0

이 그대로 - - 지금은 위의 두 가지 답변입니다 그리고 그들은 모두 오래이다 (그리고 , TL 박사 나는 새로운 사용하기 시작 내 경험에서 요약을 쓰기 때문에, 너무 짧은 IMHO) java.time의 (라이브러리를 적용 Java 버전에 대한 다른 답변에서 언급 한 바와 같이 8 이상). ISO 8601 은 날짜를 쓰는 표준 방법을 설정합니다. YYYY-MM-DD따라서 날짜-시간 형식은 다음과 같으며 (밀리 초의 경우 0, 3, 6 또는 9 자리 일 수 있음) 서식 문자열이 필요하지 않습니다.

import java.time.Instant;
public static void main(String[] args) {
    String date="2010-10-02T12:23:23Z";
    try {
        Instant myDate = Instant.parse(date);
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

나는 그것을 필요로하지 않았지만 연도를 질문에서 코드로 얻는 것처럼 :
까다 롭고 Instant직접적으로 할 수 없으며 Calendar질문을 통해 수행 할 수 있습니다 . 현재 연도의 정수 값을 JavaJava변환하십시오. 달력에 시간이 있지만 형식이 고정되어 있으므로 IMHO는 하위 문자열을 사용하는 것이 더 간단합니다.

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