用短月解析一个没有点的月份

Jal*_*lil 15 java locale date-format

我有一个字符串,表示法语区域的日期:09-oct-08:

我需要解析那个String,所以我想出了这个SimpleDateFormat:

String format2 = "dd-MMM-yy";
Run Code Online (Sandbox Code Playgroud)

但是我对月份部分有一个问题,似乎预计会有一个结束点:

df2.format(new Date());
Run Code Online (Sandbox Code Playgroud)

给我 :

 28-oct.-09
Run Code Online (Sandbox Code Playgroud)

现在什么是让我理解SimpleDateFormat("09-oct-08")的最好方法?

完整代码:

String format2 = "dd-MMM-yy"; 
DateFormat df2 = new SimpleDateFormat(format2,Locale.FRENCH); 
date = df2.parse("09-oct-08"); 
Run Code Online (Sandbox Code Playgroud)

这给了我:java.text.ParseException:Unparseable date:"09-oct-08"

如果我然后尝试记录:

df2.format(new Date()); 
Run Code Online (Sandbox Code Playgroud)

我明白了:28-oct.-09

Jac*_*eow 6

这似乎有效:

    DateFormatSymbols dfsFr = new DateFormatSymbols(Locale.FRENCH);
    String[] oldMonths = dfsFr.getShortMonths();
    String[] newMonths = new String[oldMonths.length];
    for (int i = 0, len = oldMonths.length; i < len; ++ i) {
        String oldMonth = oldMonths[i];

        if (oldMonth.endsWith(".")) {
            newMonths[i] = oldMonth.substring(0, oldMonths[i].length() - 1);
        } else {
            newMonths[i] = oldMonth;
        }
    }
    dfsFr.setShortMonths(newMonths);
    DateFormat dfFr = new SimpleDateFormat(
        "dd-MMM-yy", dfsFr);

    // English date parser for creating some test data.
    DateFormat dfEn = new SimpleDateFormat(
        "dd-MMM-yy", Locale.ENGLISH);
    System.out.println(dfFr.format(dfEn.parse("10-Oct-09")));
    System.out.println(dfFr.format(dfEn.parse("10-May-09")));
    System.out.println(dfFr.format(dfEn.parse("10-Feb-09")));
Run Code Online (Sandbox Code Playgroud)

编辑:看起来像圣影打败了我.


Bas*_*que 6

java.time

\n\n

让\xe2\x80\x99s 看看java.time框架是否可以提供帮助。

\n\n

关于 java.time

\n\n

Java 8 中内置的java.time框架以及后来的版本取代了麻烦的旧 java.util.Date/.Calendar 类。新类的灵感来自于非常成功的Joda-Time框架,该框架旨在作为其继承者,概念相似,但经过重新架构。由JSR 310定义。由ThreeTen-Extra项目扩展。请参阅教程

\n\n

LocalDate

\n\n

与旧的类不同,java.time 提供的LocalDate类表示仅日期值,没有时间或时区。

\n\n

法语缩写

\n\n

看一下 java.time 中的格式化程序对en Fran\xc3\xa7ais中缩写月份名称的期望。

\n\n

我们可以循环枚举Month来获取月份列表。该枚举提供了getDisplayName生成月份本地化名称的方法。此代码演示了该方法产生与 java.time 格式化程序相同的输出。

\n\n
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "dd-MMM-yyyy" ).withLocale ( Locale.FRENCH );\nfor ( Month month : Month.values () ) {\n    LocalDate localDate = LocalDate.of ( 2015 , month.getValue () , 1 );\n    String output = formatter.format ( localDate );\n    String displayName = month.getDisplayName ( TextStyle.SHORT , Locale.FRENCH );\n    System.out.println ( "output: " + output + " | displayName: " + displayName );// System.out.println ( "input: " + input + " \xe2\x86\x92 " + localDate + " \xe2\x86\x92 " + output );\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "dd-MMM-yyyy" ).withLocale ( Locale.FRENCH );\nfor ( Month month : Month.values () ) {\n    LocalDate localDate = LocalDate.of ( 2015 , month.getValue () , 1 );\n    String output = formatter.format ( localDate );\n    String displayName = month.getDisplayName ( TextStyle.SHORT , Locale.FRENCH );\n    System.out.println ( "output: " + output + " | displayName: " + displayName );// System.out.println ( "input: " + input + " \xe2\x86\x92 " + localDate + " \xe2\x86\x92 " + output );\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们发现 3 个字母和 4 个字母的混合拼写。较长的名称缩写为四个字符加一个句点 (句号)。四个月的名称足够短,可以不缩写地使用:mars, mai, juin, ao\xc3\xbbt

\n\n

因此,正如其他答案中所讨论的,没有简单的解决方案。

\n\n

修复数据源

\n\n

我的第一个建议是修复您的数据源。该来源显然没有遵循正确的法国缩写规则。耶鲁同意 Java 8\xe2\x80\x99s 对法语的理解。顺便说一句,如果修复您的数据源,我强烈建议使用四位数的年份,因为二位数会导致无休止的混乱和歧义。

\n\n

修复输入

\n\n

当然,来源可能超出您的控制/影响。在这种情况下,与其他答案一样,您可能需要进行强力替换,而不是尝试任何聪明的做法。另一方面,如果您输入的唯一问题只是缺少句点(句号),那么您可以使用枚举进行软编码,Month而不是对不正确的值进行硬编码。

\n\n

我会进行初步解析尝试。DateTimeParseException在尝试修复之前,先捕获 的陷阱。如果抛出异常,则修复输入。

\n\n

要修复输入,请通过循环可能的枚举实例集来尝试一年中的每个月。对于每个月,获取其缩写名称。从该缩写中去掉句点(句号),以匹配我们怀疑的不正确的传入值。测试看看它是否确实与输入匹配。如果没有,请转到下个月。

\n\n

当我们确实获得匹配项时,将输入修复为 Locale\xe2\x80\x99s 规则(在我们的例子中为法语规则)的正确缩写。然后解析固定输入。这将是我们的第二次解析尝试,因为我们在顶部进行了初步尝试。如果第二次尝试失败,则表明存在严重错误,如此处所示FIXME:。但通常情况下,第二次解析尝试会成功,我们可以跳出for枚举循环Month

\n\n

最后,您可以通过测试结果是否仍然是最初设置的伪造标志值来验证是否成功 ( LocalDate.MIN)。

\n\n
String input = "09-oct-08"; // Last two digits are Year.\nDateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "dd-MMM-yy" ).withLocale ( Locale.FRENCH );\nLocalDate localDate = LocalDate.MIN; // Some folks prefer a bogus default value as a success/failure flag rather than using a NULL.\ntry {\n    localDate = LocalDate.parse ( input , formatter );\n} catch ( DateTimeParseException e ) {\n    // Look for any month name abbreviation improperly missing the period (FULL STOP).\n    for ( Month month : Month.values () ) {\n        String abbreviation = month.getDisplayName ( TextStyle.SHORT , Locale.FRENCH );\n        String abbreviationWithoutFullStop = abbreviation.replace ( "." , "" ); // Get short abbreviation, but drop any period (FULL STOP).\n        String proper = "-" + abbreviation + "-";\n        String improper = "-" + abbreviationWithoutFullStop + "-";\n        if ( input.contains ( improper ) ) {\n            String inputFixed = input.replace ( improper , proper );\n            try {\n                localDate = LocalDate.parse ( inputFixed , formatter );\n            } catch ( DateTimeParseException e2 ) {\n                // FIXME: Handle this error. We expected this second parse attempt to succeed.\n            }\n            break; // Bail-out of the loop as we got a hit, matching input with a particular improper value.\n        }\n    }\n}\nBoolean success =  ! ( localDate.equals ( LocalDate.MIN ) );\nString formatted = formatter.format ( localDate );;\nString outputImproper = formatted.replace ( "." , "" );  // Drop any period (FULL STOP).\n
Run Code Online (Sandbox Code Playgroud)\n\n

转储到控制台。

\n\n
System.out.println ( "success: " + success + ". input: " + input + " \xe2\x86\x92 localDate: " + localDate + " \xe2\x86\x92 formatted: " + formatted + " \xe2\x86\x92 outputImproper: " + outputImproper );\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

成功:真实。输入:09-oct-08 \xe2\x86\x92 本地日期:2008-10-09 \xe2\x86\x92 格式化:09-oct.-08 \xe2\x86\x92 输出不正确:09-oct-08

\n
\n