11

我正在开发一个阿拉伯语的网络监控项目,我想像这样转换字符串日期:

الاثنين 24 أبريل 2017 - 15:00

到 Java 8 日期对象。我怎样才能做到这一点?

4

5 回答 5

9

编辑:感谢 slim 和 Meno Hochschild 的灵感:

String dateTimeString = "الاثنين 24 أبريل 2017 - 15:00";

DateTimeFormatter formatter
        = DateTimeFormatter.ofPattern("EEEE d MMMM uuuu - HH:mm", new Locale("ar"));
LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
System.out.println(dateTime);

这打印:

2017-04-24T15:00
于 2017-04-26T18:37:04.907 回答
5

@Ole 和 @slim 的答案是有效的,但不是因为他们认为的原因。

第一次观察 - 对于给定的例子,nu-extension 是不必要的:

Oles 建议也适用于 localenew Locale("ar", "SA")而不是Locale.forLanguageTag("ar-SA-u-nu-arab"). 那么这里的 unicode-nu-extension 是什么?没有什么。下一个问题:

nu-extension 应该在这里做什么?

nu-code-word "arab"由 unicode consortium 指定以产生阿拉伯-印度数字。但是要解析的输入只有西方数字 0-9(在历史上被阿拉伯人取代并指定为代码字“latn”——顺便说一句用词不当)。因此,如果 nu-extension 真的在这里完成了它的工作,那么解析应该会失败,因为阿拉伯印度数字不是 0-9,而是:

٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩

显然,Java-8 中的新时间 API 通常不支持 nu 扩展。

是否SimpleDateFormat支持 nu 扩展?

使用以下代码的调试,我发现仅泰语数字支持 nu 扩展名(另请参阅 class 的官方 javadoc,java.util.Locale但不支持阿拉伯印度数字:

SimpleDateFormat sdf = 
    new SimpleDateFormat("EEEE d MMMM yyyy - HH:mm", Locale.forLanguageTag("ar-SA-nu-arab"));
Date d = sdf.parse(dateTimeString);
System.out.println(d);
String formatted = sdf.format(d);
System.out.println(formatted);
System.out.println(sdf.format(d).equals(dateTimeString));

sdf = new SimpleDateFormat("EEEE d MMMM uuuu - HH:mm", Locale.forLanguageTag("ar-SA-u-nu-thai"));
String thai = sdf.format(d);
System.out.println("u-nu-thai: " + thai);

我假设DateTimeFormatterJava-8 类也支持泰语数字。

结论:

忘记 nu 扩展名。只需通过不带 unicode 扩展的老式方式构建语言环境,并以这种方式调整 Oles 回答。它之所以有效,是因为您的输入只有西方数字 0-9。

对于广泛的 i18n 支持,包括各种编号系统的 nu 扩展(如果您有这样的输入),您可以考虑使用外部库(例如 ICU4J 或我的 lib Time4J)。

于 2017-04-29T07:32:23.397 回答
2

我对阿拉伯语的了解不足,无法理解阿拉伯语格式的日期。但是这段代码:

Locale arabicLocale = new Locale.Builder().setLanguageTag("ar-SA-u-nu-arab").build();

LocalDate date = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(arabicLocale);

String formatted = date.format(formatter);
System.out.println(formatted);
System.out.println(formatter.parse(formatted));

产生这个输出:

26 أبريل, 2017
{},ISO resolved to 2017-04-26

创建的代码来自对设置阿拉伯编号系统区域设置Locale的答案不显示阿拉伯数字

您可以通过定义自己的FormatStyle.

于 2017-04-26T16:28:03.947 回答
0

您必须在解析字符串时指定字符集,假设您要解析的日期将始终采用您提供的格式,这将起作用:

public static Date getDate(String strDate) throws Exception{
    strDate=new String(strDate.getBytes(),"UTF-8");

    Map<String, Integer> months = new HashMap<>();

    String JAN =  new String("يناير".getBytes(), "UTF-8");
    String FEB =  new String("فبراير".getBytes(), "UTF-8");
    String MAR =  new String("مارس".getBytes(), "UTF-8");
    String APR =  new String("أبريل".getBytes(), "UTF-8");
    String APR_bis =  new String("ابريل".getBytes(), "UTF-8");
    String MAY =  new String("ماي".getBytes(), "UTF-8");
    String JUN =  new String("بونيو".getBytes(), "UTF-8");
    String JUN_bis =  new String("يونيه".getBytes(), "UTF-8");
    String JUL =  new String("يوليوز".getBytes(), "UTF-8");
    String AUG =  new String("غشت".getBytes(), "UTF-8");
    String SEP =  new String("شتنبر".getBytes(), "UTF-8");
    String SEP_bis =  new String("سبتمبر".getBytes(), "UTF-8");
    String OCT =  new String("أكتوبر".getBytes(), "UTF-8");
    String OCT_bis =  new String("اكتوبر".getBytes(), "UTF-8");
    String NOV =  new String("نونبر".getBytes(), "UTF-8");
    String NOV_bis =  new String("نوفمبر".getBytes(), "UTF-8");
    String DEC =  new String("دجنبر".getBytes(), "UTF-8");
    String DEC_bis =  new String("ديسمبر".getBytes(), "UTF-8");



    months.put(JAN, 0);
    months.put(FEB, 1);
    months.put(MAR, 2);
    months.put(APR, 3);
    months.put(APR_bis, 3);
    months.put(MAY, 4);
    months.put(JUN, 5);
    months.put(JUN_bis, 5);
    months.put(JUL, 6);
    months.put(AUG, 7);
    months.put(SEP, 8);
    months.put(SEP_bis, 8);
    months.put(OCT, 9);
    months.put(OCT_bis, 9);
    months.put(NOV, 10);
    months.put(NOV_bis, 10);
    months.put(DEC, 11);
    months.put(DEC_bis, 11);


    StringTokenizer stringTokenizer = new StringTokenizer(strDate);

    Calendar calendar = Calendar.getInstance();


    while(stringTokenizer.hasMoreElements()) {

        stringTokenizer.nextElement();// to skip the first string which is the name of the day

        int day = Integer.parseInt(stringTokenizer.nextElement().toString().trim());

        String strMonth = stringTokenizer.nextElement().toString().trim();

        int month = months.get(strMonth);

        int year = Integer.parseInt(stringTokenizer.nextElement().toString().trim());

        calendar.set(year, month, day);


    }
    return calendar.getTime();

}

它给出了这个输出:

  Fri Oct 20 15:26:47 WEST 2017
于 2017-04-27T14:27:15.823 回答
0

一种解决方案可能是将日期翻译成英文然后解析它:

private final static Map<String, Integer> monthMapping = new HashMap<>();
static {
    // list of all month.
    monthMapping.put("أبريل", "4");
}


public Date fromArabicToDate(String arabicInput) throws ParseException {
    String[] parts = arabicInput.split(" ");
    if (parts.length != 4) 
        throw new IllegalArgumentException();

    String dateInput = parts[0] + "-" + monthMapping.get(parts[1]) + "-" + parts[2];
    SimpleDateFormat parser = new SimpleDateFormat("YYYY-MM-DD");
    return parser.parse(dateInput);
}

我试图复制月份,但我不相信我做得正确。put解析时切换的参数。

或者你看看Joda-Time。也许他们有解决办法。这里提到了

于 2017-04-26T15:32:40.667 回答