Date parsing issue with Arabic and regular date in Java

北战南征 提交于 2021-01-27 05:49:49

问题


I have a date converter function like:

public static LocalDate getLocalDateFromString(String dateString) {
    DecimalStyle defaultDecimalStyle = DateTimeFormatter.ISO_LOCAL_DATE.getDecimalStyle();
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE.withDecimalStyle(defaultDecimalStyle.withZeroDigit('\u0660'));
    LocalDate date = LocalDate.parse(dateString, dateTimeFormatter);
    return date;
}

It works fine for Arabic dates like ٢٠١٩-٠٤-١٥, but when I pass a normal date like 2019-07-31, it throws an exception because the formatter is of a different type:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2019-07-31' could not be parsed at index 0

I don't have control over the date passed, as it is passed by the user.

How can I use the same function to parse both dates?


回答1:


Know your string

DateTimeFormatter doesn’t make this very easy for you. I am speculating that there may be a purpose behind this choice: it’s better if you can bring yourself into a situation where you know beforehand what kind of digits is used in the string you are going to parse. You may give this a thought: could you persuade the source of your string to pass this information to you?

Take a taste and act accordingly

If not, of course there is a way through. The following is low-level but should be general.

public static LocalDate getLocalDateFromString(String dateString) {
    DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE;
    // Take a digit from dateString to determine which digits are used
    char sampleDigit = dateString.charAt(0);
    if (Character.isDigit(sampleDigit)) {
        // Subtract the numeric value of the digit to find the zero digit in the same digit block
        char zeroDigit = (char) (sampleDigit - Character.getNumericValue(sampleDigit));
        assert Character.isDigit(zeroDigit) : zeroDigit;
        assert Character.getNumericValue(zeroDigit) == 0 : zeroDigit;
        DecimalStyle defaultDecimalStyle = dateFormatter.getDecimalStyle();
        dateFormatter = dateFormatter
                .withDecimalStyle(defaultDecimalStyle.withZeroDigit(zeroDigit));
    }
    // If the examined char wasn’t a digit, the following parsing will fail;
    // but in that case the best we can give the caller is the exception from that failed parsing.
    LocalDate date = LocalDate.parse(dateString, dateFormatter);
    return date;
}

Let’s try it out:

    System.out.println("Parsing Arabic date string to  "
            + getLocalDateFromString("٢٠١٩-٠٤-١٥"));
    System.out.println("Parsing Western date string to "
            + getLocalDateFromString("2019-07-31"));

Output from this snippet is:

Parsing Arabic date string to  2019-04-15
Parsing Western date string to 2019-07-31



回答2:


I think a better solution is to override the method in your class.




回答3:


Two formatters

If you are expecting either of two formats in your incoming strings, establish two DateTimeFormatter objects, one for each expected format.

Try both

Try one formatter, trapping for the DateTimeParseException. If thrown, try the other. If the second throws as well, then you know you’ve received unexpected faulty input.

If you have more than two expected formats, collect all the possible DateTimeFormatter objects. The loop the collection, try each to parse the input, until one does not throw the parsing exception.



来源:https://stackoverflow.com/questions/55017576/date-parsing-issue-with-arabic-and-regular-date-in-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!