【问题标题】:Parsing date in polish locale in Joda?在 Joda 的波兰语环境中解析日期?
【发布时间】:2014-11-04 22:05:05
【问题描述】:

我有以下日期:

例如。 String rawDate = "pon, 17 lis 2014, 15:51:12";

我想解析它。

我打电话:

DateTime time = new DateTimeFormatterBuilder()
                    .append(DateTimeFormat.forPattern("EEE, dd MMM yyyy, HH:mm:ss")
                            .getParser())
                    .toFormatter().withLocale(new Locale("pl")).parseDateTime(rawDate);

但我明白了:

java.lang.IllegalArgumentException: Invalid format: "pon, 17 lis 2014, 15:51:12"

【问题讨论】:

    标签: java jodatime polish


    【解决方案1】:

    显然 Joda Time(或 Java)认为 poniedziałek 的缩写形式是 pn,而不是 pon - 所以这段代码可以工作(并且比你的略简单):

    import org.joda.time.*;
    import org.joda.time.format.*;
    import java.util.*;
    
    public class Test {
        public static void main(String[] args) throws Exception {
            String rawDate = "pn, 17 lis 2014, 15:51:12";
            DateTimeFormatter parser = DateTimeFormat
                .forPattern("EEEE, dd MMM yyyy, HH:mm:ss")
                .withLocale(new Locale("pl"));
            DateTime time = parser.parseDateTime(rawDate);
            System.out.println(time);
        }
    }
    

    如果您无法更改输入,也许您可​​以更改与语言环境相关的符号?

    【讨论】:

    • 如何更改与语言环境相关的符号?
    • @pixel:令人讨厌的是,目前还不清楚你怎么做——即使Locale.Builder 在这方面也无济于事。您可以改用SimpleDateFormat,并为构造函数指定DateFormatSymbols - 但我看不到如何在Joda Time 中使用它们。如果您在为特定语言环境提取的 DateFormatSymbols 中设置新值,这可能会持续存在 - 但我还没有检查过。
    【解决方案2】:

    好问题!

    JDK 使用自己的文本资源。所以遵循 Java-8-code 会产生异常:

    String input = "pon, 17 lis 2014, 15:51:12";
    
    DateTimeFormatter dtf1 = 
      DateTimeFormatter.ofPattern("EEE, dd MMM yyyy, HH:mm:ss", new Locale("pl"));
    LocalDateTime ldt1 = LocalDateTime.parse(input, dtf1);
    System.out.print(ldt1);
    // error message:
    // java.time.format.DateTimeParseException:
    // Text 'pon, 17 lis 2014, 15:51:12' could not be parsed at index 0
    

    如果我们尝试找出问题所在,那么我们会发现 JDK 使用“Pn”:

    DateTimeFormatter dtf1 = 
      DateTimeFormatter.ofPattern("EEE, dd MMM yyyy, HH:mm:ss", new Locale("pl"));
    String output = LocalDateTime.of(2014, 11, 17, 15, 51, 12).format(dtf1);
    System.out.println(output); // "Pn, 17 lis 2014, 15:51:12"
    LocalDateTime ldt1 = LocalDateTime.parse(output, dtf1);
    

    通常人们无法更改输入。幸运的是,有一种解决方法可以定义您自己的文本资源:

    String input = "pon, 17 lis 2014, 15:51:12";
    
    TemporalField field = ChronoField.DAY_OF_WEEK;
    Map<Long,String> textLookup = new HashMap<>();
    textLookup.put(1L, "pon");
    textLookup.put(2L, "wt");
    textLookup.put(3L, "\u0347r"); // śr
    textLookup.put(4L, "czw");
    textLookup.put(5L, "pt");
    textLookup.put(6L, "sob");
    textLookup.put(7L, "niedz");
    
    DateTimeFormatter dtf2 = 
      new DateTimeFormatterBuilder()
      .appendText(field, textLookup)
      .appendPattern(", dd MMM yyyy, HH:mm:ss")
      .toFormatter()
      .withLocale(new Locale("pl"));
    LocalDateTime ldt2 = LocalDateTime.parse(input, dtf2);
    System.out.print(ldt2);
    // output: 2014-11-17T15:51:12
    

    好的,现在关于(旧的)Joda-Time。它缺少像appendText(field, lookupMap) 这样的方法。但是我们可以为 DateTimeParser 编写一个实现:

      final Map<String, Integer> textLookup = new HashMap<String, Integer>();
      textLookup.put("pon", 1);
      textLookup.put("wt", 2);
      textLookup.put("\u0347r", 3); // śr
      textLookup.put("czw", 4);
      textLookup.put("pt", 5);
      textLookup.put("sob", 6);
      textLookup.put("niedz", 7);
    
      DateTimeParser parser =
        new DateTimeParser() {
        @Override
        public int estimateParsedLength() {
            return 5;
        }
        @Override
        public int parseInto(DateTimeParserBucket bucket, String text, int position) {
            for (String key : textLookup.keySet()) {
                if (text.startsWith(key, position)) {
                    int val = textLookup.get(key);
                    bucket.saveField(DateTimeFieldType.dayOfWeek(), val);
                    return position + key.length();
                }
            }
            return ~position;
        }
      };
      DateTimeFormatter dtf =
        new DateTimeFormatterBuilder().append(parser)
        .appendPattern(", dd MMM yyyy, HH:mm:ss").toFormatter()
        .withLocale(new Locale("pl"));
      String input = "pon, 17 lis 2014, 15:51:12";
      LocalDateTime ldt = LocalDateTime.parse(input, dtf);
      System.out.println(ldt); // 2014-11-17T15:51:12.000
    

    最后问你一个问题:在 Unicode-CLDR-data 中,在缩写的工作日名称后面使用一个点,例如“pon”。而不是“pon”(我自己的库也使用 CLDR 内容)。根据您的语言知识和对波兰语的感觉,什么更常见?是否使用点?

    【讨论】:

    • 更常见的是使用点。我的情况相当不典型;)
    • @pixel 感谢您的回答。好吧,使用 dot 我的库 Time4J 将提供一个非常简单的解决方案;-) 否则,您似乎无论如何都必须定义自己的文本资源 - 等于您使用的库。每个库都可以使用这种解决方法,即使旧的java.text.SimpleDateFormat 使用DateFormatSymbols
    猜你喜欢
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多