SimpleDateFormat throws ParseException With Error Offset 0

前端 未结 4 1163
情书的邮戳
情书的邮戳 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

    Is your locale "EN"? If you use English names for the date, make sure you are using that locale

    0 讨论(0)
  • 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
    
    0 讨论(0)
  • 2021-01-23 05:09

    SimpleDateFormat is absolutely locale-sensitive. Certain fields, like hours and minutes, are locale-independent.

    SimpleDateFormat also supports localized date and time pattern strings. In these strings, the pattern letters described above may be replaced with other, locale dependent, pattern letters. SimpleDateFormat does not deal with the localization of text other than the pattern letters; that's up to the client of the class.

    Or, you can use the localization-friendly DateFormat#getDateInstance() factory method instead, since:

    public SimpleDateFormat(String pattern, Locale locale)

    Constructs a SimpleDateFormat using the given pattern and the default date format symbols for the given locale. Note: This constructor may not support all locales. For full coverage, use the factory methods in the DateFormat class.

    Source: https://stackoverflow.com/a/5174712/2591612

    0 讨论(0)
  • 2021-01-23 05:15

    If you don't specify a Locale to the formatter when you construct it, it uses your default Locale which apparently doesn't spell days and months in English.

    So specify one to the formatter that does.

    final DateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", Locale.UK);
    
    0 讨论(0)
提交回复
热议问题