Illegal pattern character 'T' when parsing a date string to java.util.Date

后端 未结 3 419
野性不改
野性不改 2020-11-22 10:03

I have a date string and I want to parse it to normal date use the java Date API,the following is my code:

public static void main(String[] args) {
    Strin         


        
相关标签:
3条回答
  • 2020-11-22 10:19

    There are two answers above up-to-now and they are both long (and tl;dr too short IMHO), so I write summary from my experience starting to use new java.time library (applicable as noted in other answers to Java version 8+). ISO 8601 sets standard way to write dates: YYYY-MM-DD so the format of date-time is only as below (could be 0, 3, 6 or 9 digits for milliseconds) and no formatting string necessary:

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

    I did not need it, but as getting year is in code from the question, then:
    it is trickier, cannot be done from Instant directly, can be done via Calendar in way of questions Get integer value of the current year in Java and Converting java.time to Calendar but IMHO as format is fixed substring is more simple to use:

    myDate.toString().substring(0,4);
    
    0 讨论(0)
  • 2020-11-22 10:28

    Update for Java 8 and higher

    You can now simply do Instant.parse("2015-04-28T14:23:38.521Z") and get the correct thing now, especially since you should be using Instant instead of the broken java.util.Date with the most recent versions of Java.

    You should be using DateTimeFormatter instead of SimpleDateFormatter as well.

    Original Answer:

    The explanation below is still valid as as what the format represents. But it was written before Java 8 was ubiquitous so it uses the old classes that you should not be using if you are using Java 8 or higher.

    This works with the input with the trailing Z as demonstrated:

    In the pattern the T is escaped with ' on either side.

    The pattern for the Z at the end is actually XXX as documented in the JavaDoc for SimpleDateFormat, it is just not very clear on actually how to use it since Z is the marker for the old TimeZone information as well.

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

    Produces the following output:

    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
    
    0 讨论(0)
  • 2020-11-22 10:44

    tl;dr

    Use java.time.Instant class to parse text in standard ISO 8601 format, representing a moment in UTC.

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

    ISO 8601

    That format is defined by the ISO 8601 standard for date-time string formats.

    Both:

    • java.time framework built into Java 8 and later (Tutorial)
    • Joda-Time library

    …use ISO 8601 formats by default for parsing and generating strings.

    You should generally avoid using the old java.util.Date/.Calendar & java.text.SimpleDateFormat classes as they are notoriously troublesome, confusing, and flawed. If required for interoperating, you can convert to and fro.

    java.time

    Built into Java 8 and later is the new java.time framework. Inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project.

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

    Convert to the old class.

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

    Time Zone

    If needed, you can assign a time zone.

    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.
    

    Convert.

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

    Joda-Time

    UPDATE: The Joda-Time project is now in maintenance mode. The team advises migration to the java.time classes.

    Here is some example code in 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.
    

    Convert to old class. Note that the assigned time zone is lost in conversion, as j.u.Date cannot be assigned a time zone.

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

    Time Zone

    If needed, you can assign a time zone.

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


    About java.time

    The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

    The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

    To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

    You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

    Where to obtain the java.time classes?

    • Java SE 8, Java SE 9, and later
      • Built-in.
      • Part of the standard Java API with a bundled implementation.
      • Java 9 adds some minor features and fixes.
    • Java SE 6 and Java SE 7
      • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
    • Android
      • Later versions of Android bundle implementations of the java.time classes.
      • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

    The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

    0 讨论(0)
提交回复
热议问题