gpt4 book ai didi

java-8 - DateTimeFormatter 工作日似乎差了一个

转载 作者:行者123 更新时间:2023-12-03 22:31:04 24 4
gpt4 key购买 nike

我正在将现有应用程序从 Joda-Time 移植到 Java 8 java.time .

我遇到了一个问题,即解析包含“星期几”值的日期/时间字符串在我的单元测试中触发了异常。

解析时:

2016-12-21 20:50:25 Wednesday December +0000 3



使用格式:
yyyy'-'MM'-'dd' 'HH':'mm':'ss' 'EEEE' 'MMMM' 'ZZ' 'e

我得到:
java.time.format.DateTimeParseException: 
Text '2016-12-21 20:50:25 Wednesday December +0000 3'
could not be parsed: Conflict found:
Field DayOfWeek 3 differs from DayOfWeek 2 derived from 2016-12-21

当让 DateTimeFormatter指出它的期望:
String logline     = "2016-12-21 20:50:25 Wednesday December +0000";
String format = "yyyy'-'MM'-'dd' 'HH':'mm':'ss' 'EEEE' 'MMMM' 'ZZ";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format).withLocale(Locale.ENGLISH);;
ZonedDateTime dateTime = formatter.parse(logline, ZonedDateTime::from);

format = "yyyy'-'MM'-'dd' 'HH':'mm':'ss' 'EEEE' 'MMMM' 'ZZ' 'e";
formatter = DateTimeFormatter.ofPattern(format).withLocale(Locale.ENGLISH);
System.out.println(formatter.format(dateTime));

我现在得到这个输出:
2016-12-21 20:50:25 Wednesday December +0000 4

因此,问题的根本原因是 e Joda-Time 中的标志认为星期一是 1 Java 8 java.time认为星期一是 0 .

现在对于 java.time.DateTimeFormatter 的模式我在 the Oracle documentation 中都找到了支持在 JSR-310 中:
e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
2 的这个显式示例而“星期二”让我相信星期三在 java.time 中也应该是 3而不是 4 .

这里有什么问题?
我误解了吗?
这是 Java 8 中的错误吗?

最佳答案

Joda-Time 和 java.time 的方式有所不同。解释模式 e .

在 Joda-Time,e图案designates the numeric value of day-of-week :

Symbol  Meaning        Presentation  Examples
------ ----------- ------------ -------
e day of week number 2

所以,使用 e相当于从日期对象获取星期几:
// using org.joda.time.DateTime and org.joda.time.format.DateTimeFormat
DateTime d = new DateTime(2016, 12, 21, 20, 50, 25, 0, DateTimeZone.UTC);
DateTimeFormatter fmt = DateTimeFormat.forPattern("e").withLocale(Locale.ENGLISH);
System.out.println(d.toString(fmt)); // 3
System.out.println(d.getDayOfWeek()); // 3
System.out.println(d.dayOfWeek().getAsText(Locale.ENGLISH)); // Wednesday

请注意,格式化程序和 getDayOfWeek()返回 3 . getDayOfWeek() method返回 DateTimeConstants class 中定义的值, 和 Wednesday's value is 3 ( the third day of the week 根据 ISO's definition )。

java.time API,模式 e has a different meaning :
Pattern  Count  Equivalent builder methods
------- ----- --------------------------
e 1 append special localized WeekFields element for numeric day-of-week

它使用本地化的 WeekFields 元素,这可能会根据语言环境而有所不同。与 getDayOfWeek() 相比,行为可能有所不同。方法:
ZonedDateTime z = ZonedDateTime.of(2016, 12, 21, 20, 50, 25, 0, ZoneOffset.UTC);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("e", Locale.ENGLISH);
System.out.println(z.format(fmt)); // 4
System.out.println(z.getDayOfWeek()); // WEDNESDAY
System.out.println(z.getDayOfWeek().getValue()); // 3

请注意,格式化程序使用英语语言环境的本地化星期几,值为 4 ,同时调用 getDayOfWeek().getValue()返回 3 .

那是因为 e使用英语语言环境等同于使用 java.time.temporal.WeekFields :
// using localized fields
WeekFields wf = WeekFields.of(Locale.ENGLISH);
System.out.println(z.get(wf.dayOfWeek())); // 4

getDayOfWeek()相当于使用 ISO 的定义:
// same as getDayOfWeek()
System.out.println(z.get(WeekFields.ISO.dayOfWeek())); // 3

这是因为 ISO 的定义使用星期一作为一周的第一天,而 WeekFields英语语言环境使用星期日:
// comparing the first day of week
System.out.println(WeekFields.ISO.getFirstDayOfWeek()); // MONDAY
System.out.println(wf.getFirstDayOfWeek()); // SUNDAY

所以 e模式的行为可能与 getDayOfWeek() 不同或不同,根据格式化程序中设置的语言环境(或 JVM 默认语言环境,如果未设置)。例如,在法语语言环境中,它的行为类似于 ISO,而在某些阿拉伯语语言环境中,一周的第一天是星期六:
WeekFields.of(Locale.FRENCH).getFirstDayOfWeek(); // MONDAY
WeekFields.of(new Locale("ar", "AE")).getFirstDayOfWeek(); // SATURDAY

根据 javadoc ,返回星期几的数值的唯一模式似乎是本地化的。因此,解析输入 2016-12-21 20:50:25 Wednesday December +0000 3 ,您可以使用 java.time.format.DateTimeFormatterBuilder并用 java.time.temporal.ChronoField 加入日期/时间模式指示星期几的数值(ISO 非区域设置敏感字段):
String input = "2016-12-21 20:50:25 Wednesday December +0000 3";
DateTimeFormatter parser = new DateTimeFormatterBuilder()
// date/time pattern
.appendPattern("yyyy-MM-dd HH:mm:ss EEEE MMMM ZZ ")
// numeric day of week
.appendValue(ChronoField.DAY_OF_WEEK)
// create formatter with English locale
.toFormatter(Locale.ENGLISH);

ZonedDateTime date = ZonedDateTime.parse(input, parser);

另请注意,您不需要引用 - , :和空格字符,因此模式变得更加清晰易读(IMO)。

我还设置了英语语言环境,因为如果不设置,它将使用 JVM 默认语言环境,并且不保证始终是英语。并且它也可以在没有通知的情况下更改,即使在运行时,所以最好指定一个,特别是如果您已经知道输入的语言是什么。

更新 : 可能是 ccccc模式应该可以工作,因为它相当于 appendText(ChronoField.DAY_OF_WEEK, TextStyle.NARROW_STANDALONE)在我的测试(JDK 1.8.0_144)中,它返回(并解析) 3 :
DateTimeFormatter parser = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss EEEE MMMM ZZ ccccc", Locale.ENGLISH);
ZonedDateTime date = ZonedDateTime.parse(input, parser);

关于java-8 - DateTimeFormatter 工作日似乎差了一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46341152/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com