DateTimeFormatter 工作日似乎少了一位

2024-01-30

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

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

解析时:

2016-12-21 20:50:25 十二月星期三 +0000 3

使用格式:

yyyy'-'MM'-'dd' 'HH':'mm':'ss' 'EEEE' 'MMMM' 'ZZ' 'e

I get:

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

所以实际上问题的根本原因是eJoda-Time 中的标志认为星期一是1然而Java 8java.time认为星期一是0.

现在对于模式java.time.DateTimeFormatter我在两者中都找到了支持Oracle 文档 https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns在 JSR-310 中:

e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T

这个明确的例子2而“星期二”让我相信星期三在 java.time 中也应该是3代替4.

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


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


在乔达时代,e图案指定星期几的数值 http://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html:

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() return 3. The getDayOfWeek() method http://www.joda.org/joda-time/apidocs/org/joda/time/base/AbstractDateTime.html#getDayOfWeek--返回定义在中的值DateTimeConstants class http://www.joda.org/joda-time/apidocs/org/joda/time/DateTimeConstants.html, and 星期三的值为3 http://www.joda.org/joda-time/apidocs/org/joda/time/DateTimeConstants.html#WEDNESDAY (一周中的第三天 https://www.timeanddate.com/calendar/days/wednesday.html根据ISO的定义 https://www.timeanddate.com/calendar/days/).


In java.timeAPI,模式e 有不同的意义 https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatterBuilder.html#appendPattern-java.lang.String-:

Pattern  Count  Equivalent builder methods
-------  -----  --------------------------
e        1      append special localized WeekFields element for numeric day-of-week

它使用本地化的WeekFields https://docs.oracle.com/javase/8/docs/api/java/time/temporal/WeekFields.html元素,这可能会根据区域设置而有所不同。与getDayOfWeek() method:

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

While 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

So the e模式可能表现不同或不同getDayOfWeek(),根据格式化程序中设置的区域设置(或 JVM 默认区域设置,如果未设置)。例如,在法语语言环境中,它的行为与 ISO 类似,而在某些阿拉伯语语言环境中,一周的第一天是星期六:

WeekFields.of(Locale.FRENCH).getFirstDayOfWeek(); // MONDAY
WeekFields.of(new Locale("ar", "AE")).getFirstDayOfWeek(); // SATURDAY

根据javadoc https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatterBuilder.html#appendPattern-java.lang.String-,唯一返回星期几的数值的模式似乎是本地化的模式。因此,解析输入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 默认语言环境,并且不能保证始终为英语。即使在运行时,它也可以在没有通知的情况下进行更改,因此最好指定一个,特别是如果您已经知道输入是什么语言的话。


Update: 大概是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);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DateTimeFormatter 工作日似乎少了一位 的相关文章

随机推荐

  • PHP 的 unlink 函数可以与路径一起使用吗?

    我想从 PHP 中的文件夹中删除文件 但我只有该文件的路径 是否可以提供取消链接的路径 例如 unlink path to file txt 如果这不起作用 删除这些文件的唯一方法是在 path to 目录中创建一个 php 文件 并将其以
  • 改变架构生成器中的列长度?

    我有两个字段需要增加字符限制 我通读了文档 令我惊讶的是我没有找到它的选项 可以做吗 如果不是 我应该如何解决这个问题 我可以删除该列并使用正确的属性重新创建它 但我不想丢失数据库中的任何数据 对于 Laravel 4 DB update
  • mysql、准备好的语句和自动类型转换

    我使用常规语句和准备好的语句执行完全相同的查询时得到不同的结果 我认为这是一个类型转换错误 mysql gt show columns from server where field vlan Field Type Null Key Def
  • 在 Android 中缓存文件的最佳实践

    我目前的应用程序将图像文件缓存在cache应用程序的子目录 这些图像用于ListView并存储在HashMap of SoftReferences to Bitmaps 所以我的问题是 缓存这些图像文件的最佳方法是什么 而不增加我的应用程序
  • 协助刷新 athena 表中的数据

    我编写了从 S3 上的多个外部表读取数据的查询 应用必要的过滤器 连接 然后将结果加载到目标表中以在 Athena 中进行分析 但是 随着源表中的数据刷新 我想刷新目标表 所以我打算删除并重新创建该表 但它似乎不起作用 我能够删除目标表 但
  • 为什么 ondrop 不起作用?

    我试图让拖放工作 但我将一个函数连接到 ondrop 事件 但该函数从未被调用 这是一个笨蛋 http plnkr co edit qGEdYO8okRZAR3bnZrNk p preview http plnkr co edit qGEd
  • MPMediaItems 原始歌曲数据

    我想知道如何访问 MPMediaItem 的原始数据 有任何想法吗 您可以通过以下方式获取媒体项的数据 void mediaItemToData Implement in your project the media item picker
  • 其他语言中的 Cobol 88 类型等效项是什么?

    我现在正在学习 COBOL 非常喜欢 88 类型的变量 我想知道其他语言中是否有类似的东西 也是最知名的语言 例如 C Objective C 甚至使用库 我唯一能想到的相似之处就是使用 define booleanResult varia
  • 颠倒方向在 iOS 6 中不适用于导航视图和选项卡栏视图?

    我在 ios 6 中创建了一个带有导航视图的应用程序 此外 我还在应用程序摘要中设置了所有方向选项 甚至使用了 BOOL shouldAutoRotate and NSUInteger supportedInterfaceOrientaio
  • 如何在 Java Swing 中同步两个视图

    我正在尝试这样做 在我的 GUI 中 我有一个带有自定义模型的 JTable 在 GUI 的其他部分 我有一个面板 可以在其中绘制一些箭头 我想 同步这两个视图 假设我的 JTable 中有 5 行 我将在箭头面板中绘制 5 个箭头 如果我
  • 使用 ExtJS4 从文本字段切换到显示字段

    我创建了一个在普通显示字段中显示值的表单 表单旁边有一个 编辑 按钮 一旦用户单击 显示字段应切换为文本字段 因此使数据可编辑 我猜测 这可以通过使用两种相同的表单来实现 一种可编辑 一种不可编辑 并且根据用户单击按钮的情况 其中一种或另一
  • 未知标签类型:“连续”

    我的团队伙伴 有问题 Avg SessionLength TimeonApp TimeonWebsite LengthofMembership Yearly Amount Spent 0 34 497268 12 655651 39 577
  • IE 中 jquery Accordion 的无效参数错误

    jquery 手风琴抛出 无效参数 IE 中的例外 我的是 IE8 它适用于 Firefox 和 Chrome jquery Accordion 与 IE 可能存在什么问题 这是 HTML div h3 a href Training a
  • IE9 导入内联 SVG 元素损坏

    我在用这个方法 https stackoverflow com a 9883539 494954将 SVG 文档导入到页面中 效果很好 但在 IE9 中 没有一个
  • 如何用CSS使3个元素相互重叠

    我有3个要素 div class foo div div class bar div div class foobar div I want foo重叠 bar bar重叠 foobar foobar重叠 foo 像这样 用CSS可以吗 没
  • 如何选择本示例中未使用的代码

    我有一个int我的表中的列SQL数据库 我在这张表中保留了一些代码 我的代码的示例范围是 1 9 我不需要在这个范围内使用代码 Example 使用的代码是 Select code from MyTable result is 2 6 7
  • asp.net c# 中的 System.Web.Caching.Cache.NoSlidingExpiration

    请告诉我有关System Web Caching Cache NoSlidingExpiration在 ASP NET 中 有资料了here http msdn microsoft com en us library ms178597 as
  • Django 1.9 弃用警告 app_label

    我刚刚更新到 Django v1 8 并在更新项目之前测试了本地设置 并且收到了以前从未见过的弃用警告 这对我来说也没有任何意义 我可能只是忽略了某些内容或误解了文档 Users neilhickman Sites guild ankylo
  • 使用 blockproc 或 im2col 在图像上重叠滑动窗口?

    我必须申请dct2到我的图像的小窗口 最好使用重叠窗口 我发现Matlab中有两个函数可以实现这一点blockproc and im2col 我也无法理解 希望得到一些澄清 blockproc可用于使用以下方法在滑动窗口上实现我的功能Bor
  • DateTimeFormatter 工作日似乎少了一位

    我正在将现有应用程序从 Joda Time 移植到 Java 8java time 我遇到了一个问题 解析包含 星期几 值的日期 时间字符串在单元测试中触发了异常 解析时 2016 12 21 20 50 25 十二月星期三 0000 3