SimpleDateFormat throws ParseException With Error Offset 0

前端 未结 4 1172
情书的邮戳
情书的邮戳 2021-01-23 04:19

What\'s wrong with the following code? It throws a ParseException with error offset 0.

final DateFormat df = new SimpleDateFormat(\"EEE MMM dd HH:mm:ss yyyy\");
         


        
4条回答
  •  北荒
    北荒 (楼主)
    2021-01-23 05:04

    Never use SimpleDateFormat or DateTimeFormatter without a Locale

    Since the given date-time is in English, you should use Locale.ENGLISH with your date-time parser; otherwise the parsing will fail in a system (computer, phone etc.) which is using a non-English type of locale.

    Also, note that the date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.

    • For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
    • If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

    Demo:

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            final String strDateTime = "Thu Jan 23 14:24:47 2014";
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss uuuu", Locale.ENGLISH);
            LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
            System.out.println(ldt);
        }
    }
    

    Output:

    2014-01-23T14:24:47
    

    By default, DateTimeFormatter#ofPattern uses the default FORMAT locale which the JVM sets during startup based on the host environment. Same is the case with SimpleDateFormat. I have tried to illustrate the problem through the following demo:

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            final String strDateTime = "Thu Jan 23 14:24:47 2014";          
            DateTimeFormatter dtfWithDefaultLocale = null;
    
            System.out.println("JVM's Locale: " + Locale.getDefault());
            // Using DateTimeFormatter with the default Locale
            dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss uuuu");         
            System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
            System.out.println(
                    "Parsed with JVM's default locale: " + LocalDateTime.parse(strDateTime, dtfWithDefaultLocale));
    
            // Setting the JVM's default locale to Locale.FRANCE
            Locale.setDefault(Locale.FRANCE);
            
            // Using DateTimeFormatter with Locale.ENGLISH explicitly (recommended)
            DateTimeFormatter dtfWithEnglishLocale = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss uuuu", Locale.ENGLISH);        
            System.out.println("JVM's Locale: " + Locale.getDefault());
            System.out.println("DateTimeFormatter's Locale: " + dtfWithEnglishLocale.getLocale());
            LocalDateTime zdt = LocalDateTime.parse(strDateTime, dtfWithEnglishLocale);
            System.out.println("Parsed with Locale.ENGLISH: " + zdt);
    
            
            System.out.println("JVM's Locale: " + Locale.getDefault());
            // Using DateTimeFormatter with the default Locale
            dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss uuuu");         
            System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
            System.out.println(
                    "Parsed with JVM's default locale: " + LocalDateTime.parse(strDateTime, dtfWithDefaultLocale));
        }
    }
    

    Output:

    JVM's Locale: en_GB
    DateTimeFormatter's Locale: en_GB
    Parsed with JVM's default locale: 2014-01-23T14:24:47
    JVM's Locale: fr_FR
    DateTimeFormatter's Locale: en
    Parsed with Locale.ENGLISH: 2014-01-23T14:24:47
    JVM's Locale: fr_FR
    DateTimeFormatter's Locale: fr_FR
    Exception in thread "main" java.time.format.DateTimeParseException: Text 'Thu Jan 23 14:24:47 2014' could not be parsed at index 0
        at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
        at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
        at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
        at Main.main(Main.java:33)
    

    The following demo, using SimpleDateFormat, is just for the sake of completeness:

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) throws ParseException {
            final String strDateTime = "Thu Jan 23 14:24:47 2014";
            SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", Locale.ENGLISH);
            Date date = sdf.parse(strDateTime);
            System.out.println(date);
        }
    }
    

    Output:

    Thu Jan 23 14:24:47 GMT 2014
    

提交回复
热议问题