首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >DateTimeFormatter平日似乎只差一天

DateTimeFormatter平日似乎只差一天
EN

Stack Overflow用户
提问于 2017-09-21 02:08:53
回答 2查看 4.3K关注 0票数 14

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

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

分析时:

2016年12月12日至21日20:50:25星期三12月+0000 3

使用格式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
yyyy'-'MM'-'dd' 'HH':'mm':'ss' 'EEEE' 'MMMM' 'ZZ' 'e

我得到:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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指明它期望的内容时:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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));

我现在得到了这个输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2016-12-21 20:50:25 Wednesday December +0000 4

因此,问题的根本原因在于Joda-Time中的e标志认为周一为1,而Java8 java.time则认为周一为0

对于java.time.DateTimeFormatter支持的模式,我在Oracle文档和JSR-310中都找到了以下内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T

这个明确的2和“星期二”的例子让我相信,周三也应该在java.time be 3而不是4

这里怎么了?我误解了吗?这是Java 8中的一个bug吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-21 04:17:15

在Joda-Time和java.time如何解释模式e上有一个不同之处。

在Joda-Time中,e模式指定每周一天的数值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Symbol  Meaning        Presentation  Examples
------  -----------    ------------  -------
e       day of week    number        2

因此,使用e相当于从date对象获取一周中的一天:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 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方法返回在班级3 (根据ISO定义定义的一周的第三天)中定义的值。

java.time API中,模式e 有不同的含义

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Pattern  Count  Equivalent builder methods
-------  -----  --------------------------
e        1      append special localized WeekFields element for numeric day-of-week

它使用本地化的WeekFields元素,这可能因地区而异。与getDayOfWeek()方法相比,这种行为可能有所不同:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// using localized fields
WeekFields wf = WeekFields.of(Locale.ENGLISH);
System.out.println(z.get(wf.dayOfWeek())); // 4

getDayOfWeek()等同于使用国际标准化组织的定义:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// same as getDayOfWeek()
System.out.println(z.get(WeekFields.ISO.dayOfWeek())); // 3

这是因为国际标准化组织的定义使用星期一作为一周的第一天,而带有英语语言环境的WeekFields使用的是星期日:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// comparing the first day of week
System.out.println(WeekFields.ISO.getFirstDayOfWeek()); // MONDAY
System.out.println(wf.getFirstDayOfWeek()); // SUNDAY

因此,根据格式化程序中的区域设置(如果没有设置e默认区域设置),getDayOfWeek()模式的行为可能与getDayOfWeek()不同。例如,在法语地区,它的行为就像ISO,而在一些阿拉伯地区,一周的第一天是星期六:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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连接起来,以指示一周中的数值( indicate敏感字段):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DateTimeFormatter parser = DateTimeFormatter
    .ofPattern("yyyy-MM-dd HH:mm:ss EEEE MMMM ZZ ccccc", Locale.ENGLISH);
ZonedDateTime date = ZonedDateTime.parse(input, parser);
票数 13
EN

Stack Overflow用户

发布于 2017-09-21 02:55:58

Locale.ENGLISH,星期三是一周中的第四天,因为周从星期天开始。你可以检查一周的第一天

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
WeekFields.of(Locale.ENGLISH).getFirstDayOfWeek(); //it's SUNDAY
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46341152

复制
相关文章
还在用 SimpleDateFormat, 来试试 DateTimeFormatter
1.8 以前 Java 关于日期的类是 Date 与 Calendar, 与之对应的格式化的类是 SimpleDateFormat。 上一篇介绍了在1.8 中提供的 java.time 包, Java 提供了更加丰富的时间类型来供我们使用,与之对应的格式化类型也需要使用新提供的 DateTimeFormatter。
Dylan Liu
2020/11/17
9260
还在用 SimpleDateFormat, 来试试 DateTimeFormatter
1.8 以前 Java 关于日期的类是 Date 与 Calendar, 与之对应的格式化的类是 SimpleDateFormat。 上一篇介绍了在1.8 中提供的 java.time 包, Java 提供了更加丰富的时间类型来供我们使用,与之对应的格式化类型也需要使用新提供的 DateTimeFormatter。
Dylan Liu
2020/11/23
1.4K0
localdate和localdatetime互转_datetimeformatter.ofpattern
现在LocalDateTime、LocalDate、Date之间的相互转换就完成了
全栈程序员站长
2022/11/10
1.7K0
localdate和localdatetime互转_datetimeformatter.ofpattern
Turbopack似乎并没有那么牛
这几天前端圈子有一个比较火的基建工具Turbopack,官方文档号称比vite快10倍,比webpack快700倍。今天正好有空,把官方提供的demo浅玩了一下,发现它并没有那么神。
神奇的程序员
2023/01/09
7610
Turbopack似乎并没有那么牛
JAVA日期安全格式化之SimpleDateFormat和jodaTime,DateTimeFormatter
SimpleDateFormat线程不安全的日期格式化库 SimpleDateFormat是JAVA提供的一个日期转换类。 package com.rumenz.task; import java.text.SimpleDateFormat; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; impor
开源日记
2021/01/28
6280
社区团购,尽头似乎还很远
受疫情影响社区团购再度站上了风口,众多互联网巨头纷纷入局社区团购领域,试图从中分走一块蛋糕。据企查查大数据研究院发布的《2020年社区团购投融资数据报告》显示,2020年社区团购行业公开披露的融资事件达19起,融资总金额为171.7亿元,同比增长了356.3%。
刘旷
2021/10/08
1.3K0
LocalDate的简单用法介绍
Java8的特性已经不再是“新特性”,很多Java8的类也逐渐被更多的程序员在使用。
明明如月学长
2021/08/31
8000
攻击SDN交换机,似乎很有趣
软件定义交换机似乎给网络运营商提供了许多功能,但在拉斯维加斯Black Hat 2015全球顶尖安全会议上,一篇名为《STAYING PERSISTENT IN SOFTWARE DEFINED NE
SDNLAB
2018/04/03
8040
攻击SDN交换机,似乎很有趣
将string字符串转成LocalDateTime工具类
``` public class LocalDateTimeUtil { /** * 将Long类型的时间戳转换成String 类型的时间格式,时间格式为:yyyy-MM-dd HH:mm:ss */ public static String convertTimeToString(Long time){ if (StringUtils.isEmpty(time)){ return null; } DateTimeFormatter ftf = DateTimeF
高大北
2022/06/14
4.1K0
JDK8的日期时间操作
查询当前日期(年月日)LocalDate localDate = LocalDate.now();System.out.println(localDate);//2021-11-18查询当前时间(时分秒)LocalTime localTime = LocalTime.now();String format = localTime.format(DateTimeFormatter.ofPattern("HH🇲🇲ss"));System.out.println(localTime.getHour()+":"+l
在下是首席架构师
2022/08/18
9300
java8将日期格式yyyyMM转换为LocalDate
当我们希望将一个yyyyMM格式的日期转换为LocalDate的时候,不出意外会报错java.time.format.DateTimeParseException 因为LocalDate是需要指定到具体的一天的,所以当我们想解析202211这个字符串时因为没有对应的这个月的哪一天,所以运行的时候会报错,导致无法构建LocalDate的实例。
翎野君
2023/05/12
1.4K0
JAVA8实战 - 日期API
这一节我们来讲讲JAVA8的日期类,源代码的作者其实就是Joda-Time,所以可以看到很多代码的API和Joda类比较像。日期类一直是一个比较难用的东西,但是JAVA8给日期类提供了一套新的API让日期类更加好用。
阿东
2021/08/16
1.6K0
【最爽的日期工具包LocalDate·超爽,超实用】(Java8版本)
需要的包: import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAccessor; import j
红目香薰
2022/11/28
6690
LocalDate & LocalDateTime 常用 API 互相转换
在平常时开发过程中,总有很多奇奇怪怪的时间需要互相转换,比如 Date to String , Date to DateTime , String to Date , String to DateTime ,Date to TimeStamp等等……,中间就算对JavaApi再熟悉也难免会搞混,还不如做一些简单的记录,方便日后需要用到之时直接复制出来使用即可。
BUG弄潮儿
2021/10/08
2.3K0
LocalDate & LocalDateTime 常用 API 互相转换
java 8 日期操作,真香!
java 8 的日期类已经出来很长一段时间了,一直以来也没怎么用过,最近用到了感觉太好用了,真香。
索码理
2022/09/20
6080
Jenkins安装报错:该Jenkins实例似乎已离线
打开一个新的Tab,输入网址:http://localhost:8080/pluginManager/advanced
Java架构师历程
2020/04/21
2.5K0
VMware:该虚拟机似乎正在使用中。
进入这个虚拟机虚拟文件存放的位置,也就是上图中的配置文件位置: 将下图圈起来这个.lck后缀的文件夹删除就可以
别团等shy哥发育
2023/02/25
4400
VMware:该虚拟机似乎正在使用中。
有了它,我们似乎可以告别 Stack Overflow 了?
先问大家一个问题,如果你撸代码的过程中遇到了一个问题不知道怎么解决,你一般会怎么办?
崔庆才
2020/06/29
2.5K0
有了它,我们似乎可以告别 Stack Overflow 了?
为什么不建议使用Date,而是使用Java8新的时间和日期API?
在Java 8之前,所有关于时间和日期的API都存在各种使用方面的缺陷,因此建议使用新的时间和日期API,分别从旧的时间和日期的API的缺点以及解决方法、Java 8 新的时间和日期API进行讲解。
武培轩
2019/09/16
2K0
java获取当前日期和时间(各种方法对比)
System.currentTimeMillis()产生一个当前的毫秒,这个毫秒其实就是自1970年1月1日0时起的毫秒数,类型为long; Date:
ha_lydms
2023/08/09
3K0
java获取当前日期和时间(各种方法对比)

相似问题

Spring中的日期转换只差一天

30

Joda时间: DateTimeFormatter :一天的开始

11

如何从月中的某一天起算平日

59

如何只拉取平日的前一天记录?

333

DatePicker,FullCalendar和MySQL事件的日期最后只差一天

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文