1

I have following date:

eg. String rawDate = "pon, 17 lis 2014, 15:51:12";

and I would like to parse it.

I call:

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

But I get:

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

pixel
  • 24,905
  • 36
  • 149
  • 251

2 Answers2

4

Apparently Joda Time (or Java) treats the abbreviated form of poniedziałek is pn, not pon - so this code works (and is slightly simpler than yours):

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

If you can't change your input, perhaps you can change the symbols associated with the locale?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • How can I change symbols associate with the locale? – pixel Nov 03 '14 at 22:18
  • 1
    @pixel: Annoyingly, it's not clear how you can - even `Locale.Builder` doesn't help on that front. You could use `SimpleDateFormat` instead, and specify a `DateFormatSymbols` to the constructor - but I can't see how to use them in Joda Time. It's possible that if you set new values in a `DateFormatSymbols` fetched for a particular locale, that that will stick - but I haven't checked it. – Jon Skeet Nov 03 '14 at 22:45
1

Good question!

The JDK uses its own text resources. So following Java-8-code produces an exception:

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

If we try to find out what is the problem then we find out that JDK uses "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);

Normally people cannot change the input. Fortunately, there is a workaround defining your own text resources:

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

Okay, now about (old) Joda-Time. It is missing such a method like appendText(field, lookupMap). But we can write an implementation for a 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

Finally a question to you: In Unicode-CLDR-data a dot is used behind the abbreviated weekday names, for example "pon." instead of "pon" (my own library uses the CLDR-content, too). What is more common according to your language knowledge and feeling regarding polish? Using a dot or not?

Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
  • More common is usage with a dot. My case is rather untypical ;) – pixel Nov 04 '14 at 21:55
  • @pixel Thanks for your answer. Well, with dot my library Time4J would offer a very simple solution ;-) otherwise it seems you have to define your own text resources anyway - equal which library you use. That workaround is possible with every library, even with old `java.text.SimpleDateFormat` using `DateFormatSymbols`. – Meno Hochschild Nov 05 '14 at 08:53