我正在将日期/日期时间字符串转换为OffsetDateTime
,我有一种日期时间格式,它可能有以下值之一:
yyyy-MM-dd, yyyy/MM/dd
有时有时间和没有时间,我需要将其转换为OffsetDateTime
。
我已经尝试了下面的代码
// for format yyyy-MM-dd
DateTimeFormatter DATE_FORMAT = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
.toFormatter();
因为没有时间,我将它设置为默认值,但是当我试图解析时
OffsetDateTime.parse("2016-06-06", DATE_FORMAT)
它抛出的错误类似于
线程"main"java.time.format.DateTimeParseException中的异常:无法解析文本'2016-06-06':无法从TemporalAccess:{}获取OffsetDateTime,ISO解析为2016-06-06T00:00类型java.time.format.Parsed
有人能帮我解决这个问题吗?
尝试这种方式:
if (!StringUtils.isEmpty(stringDate)){
OffsetDateTime offsetDateTime =
OffsetDateTime.from(LocalDate.parse(stringDate,
DateTimeFormatter.ofPattern("[yyyy-MM-dd][yyyy/MM/dd]")));
}
< code>OffsetDateTime需要知道相对于UTC的时区偏移量,因此您需要为此提供一个默认值。为<代码>计时字段提供默认值。偏移量_秒:
DateTimeFormatter DATE_FORMAT = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter();
或者,您拥有的格式对于< code>LocalDateTime就足够了。
要创建< code>OffsetDateTime,您需要日期(日、月和年)、时间(小时、分钟、秒和纳秒)和偏移量(与UTC的差异)。
您的输入只有日期,因此您必须构建其余的,或者为它们假设默认值。
要分析这两种格式(yyyy-MM-dd
和yy/MM/dd
),您可以使用带有可选模式的DateTimeFormatter
(由[]
]分隔)并分析为本地日期
(因为您只有日期字段):
// parse yyyy-MM-dd or yyyy/MM/dd
DateTimeFormatter parser = DateTimeFormatter.ofPattern("[yyyy-MM-dd][yyyy/MM/dd]");
// parse yyyy-MM-dd
LocalDate dt = LocalDate.parse("2016-06-06", parser);
// or parse yyyy/MM/dd
LocalDate dt = LocalDate.parse("2016/06/06", parser);
您也可以使用这个(稍微复杂一点,但工作方式相同):
// year followed by - or /, followed by month, followed by - or /, followed by day
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy[-][/]MM[-][/]dd");
然后,您可以设置构建< code>LocalDateTime的时间:
// set time to midnight
LocalDateTime ldt = dt.atStartOfDay();
// set time to 2:30 PM
LocalDateTime ldt = dt.atTime(14, 30);
或者,您也可以使用<code>解析默认值</code>,正如@greg的回答中所解释的:
// parse yyyy-MM-dd or yyyy/MM/dd
DateTimeFormatter parser = new DateTimeFormatterBuilder().appendPattern("[yyyy-MM-dd][yyyy/MM/dd]")
// set hour to zero
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
// set minute to zero
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
// create formatter
.toFormatter();
// parse the LocalDateTime, time will be set to 00:00
LocalDateTime ldt = LocalDateTime.parse("2016-06-06", parser);
请注意,我必须将小时和分钟设置为零。您还可以将秒(ChronoField.SECOND_OF_MINUTE
)和纳秒(chronof ield.NANO_OF _SECOND
)设置为零,但设置小时和分钟足以将所有其他字段设置为零。
您告诉我您想使用系统的默认偏移量。这有点棘手。
“系统的默认偏移量”将取决于系统的默认时区。一个时区可以有多个偏移量,具体取决于您在时间线中的时间。
我将使用系统的默认时区(美国/圣保罗
)作为示例。在下面的代码中,我使用的是ZoneId。systemDefault()
,但请记住,这在每个系统/环境中都是不同的。对于下面的所有示例,请记住ZoneId。systemDefault()
返回美国/圣保罗
。如果要获取特定的分区,应使用ZoneId。“zone_name”)
-实际上这是首选。
首先,您必须获取 LocalDateTime
在指定时区的有效偏移量列表:
// using the parser with parseDefaulting
LocalDateTime ldt = LocalDateTime.parse("2016-06-06", parser);
// get all valid offsets for the date/time, in the specified timezone
List<ZoneOffset> validOffsets = ZoneId.systemDefault().getRules().getValidOffsets(ldt);
根据javadoc,对于任何给定的本地日期时间,< code>validOffsets列表大小可以是零、一或二。
对于大多数情况,只有一个有效偏移量。在这种情况下,很难获得OffsetDateTime
:
// most common case: just one valid offset
OffsetDateTime odt = ldt.atOffset(validOffsets.get(0));
其他情况(零或两个有效偏移)通常是由于夏令时更改 (DST) 而发生的。
在圣保罗时区,夏令时将于2017年10月15日开始:在午夜,时钟向前移动到凌晨1点,时差从< code>-03:00变为< code>-02:00。这意味着从00:00到00:59的所有本地时间都不存在——你也可以认为时钟从23:59直接变为01:00。
因此,在圣保罗时区,该日期没有有效的偏移量:
// October 15th 2017 at midnight, DST starts in Sao Paulo
LocalDateTime ldt = LocalDateTime.parse("2017-10-15", parser);
// system's default timezone is America/Sao_Paulo
List<ZoneOffset> validOffsets = ZoneId.systemDefault().getRules().getValidOffsets(ldt);
System.out.println(validOffsets.size()); // zero
没有有效的偏移量,所以您必须决定在这种情况下做什么(使用“默认”的偏移量?抛出异常?).< br >即使您的时区今天没有DST,它也可能在过去有(过去的日期可能是这种情况),或者在未来有(因为任何国家的DST和偏移量都是由政府和法律定义的,不能保证将来没有人会改变)。
但是,如果创建一个分区日期时间
,结果将不同:
// October 15th 2017 at midnight, DST starts in Sao Paulo
LocalDateTime ldt = LocalDateTime.parse("2017-10-15", parser);
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
< code>zdt变量将为< code > 2017-10-15t 01:00-02:00[America/Sao _ Paulo]-时间和偏移量在< code>-02:00偏移量时自动调整为凌晨1点。
并且存在两个有效偏移量的情况。在圣保罗,DST 将于 2018年 2 月 18 日结束:午夜时分,时钟将向 1 小时后移到 17日的晚上 11 点,偏移量将从 -02:00
更改为 -03:00
。这意味着 23:00 到 23:59 之间的所有本地时间将同时存在两次,两种偏移量。
因为我将默认时间设置为午夜,所以只有一个有效的偏移量。但是假设我决定使用默认时间23:00:
// parse yyyy-MM-dd or yyyy/MM/dd
parser = new DateTimeFormatterBuilder().appendPattern("[yyyy-MM-dd][yyyy/MM/dd]")
// *** set hour to 11 PM ***
.parseDefaulting(ChronoField.HOUR_OF_DAY, 23)
// set minute to zero
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
// create formatter
.toFormatter();
// February 18th 2018 at midnight, DST ends in Sao Paulo
// local times from 23:00 to 23:59 at 17th exist twice
LocalDateTime ldt = LocalDateTime.parse("2018-02-17", parser);
// system's default timezone is America/Sao_Paulo
List<ZoneOffset> validOffsets = ZoneId.systemDefault().getRules().getValidOffsets(ldt);
System.out.println(validOffsets.size()); // 2
LocalDateTime
将有2个有效的偏移量。在这种情况下,您必须选择其中之一:
// DST offset: 2018-02-17T23:00-02:00
OffsetDateTime dst = ldt.atOffset(validOffsets.get(0));
// non-DST offset: 2018-02-17T23:00-03:00
OffsetDateTime nondst = ldt.atOffset(validOffsets.get(1));
但是,如果您创建一个 ZonedDateTime
,它将使用第一个偏移量作为默认值:
// February 18th 2018 at midnight, DST ends in Sao Paulo
LocalDateTime ldt = LocalDateTime.parse("2018-02-17", parser);
// system's default timezone is America/Sao_Paulo
List<ZoneOffset> validOffsets = ZoneId.systemDefault().getRules().getValidOffsets(ldt);
// by default it uses DST offset
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
zdt
将是2018-02-17T23:00-02:00[America/Sao_Paulo]
-注意它默认使用DST偏移量(-02:00
)。
如果您想要DST结束后的偏移量,您可以执行以下操作:
// get offset after DST ends
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault()).withLaterOffsetAtOverlap();
zdt
将是2018-02-17T23:00-03:00[America/Sao_Paulo]
-它使用偏移量-03:00
(DST结束后)。
只是提醒一下,系统的默认时区甚至可以在运行时更改,最好使用特定的时区名称(比如< code > zoneid . of(" America/Sao _ Paulo "))。您可以通过调用< code > zoneid . getavailablezoneids()来获取可用时区的列表(并选择最适合您系统的时区)。
问题内容: 如何将字符串日期格式转换为日期,我的日期字符串格式为 接下来,我没有运气尝试。 以上所有语句都给出了解析错误。 问题答案: 请阅读的文档time.Parse: 该布局通过显示参考时间(定义为 2006年1月2日星期一15:04:05-0700 如果它是值,将被解释;它用作输入格式的示例。然后将对输入字符串进行相同的解释。 所以正确的格式是
问题内容: 如何在python中将字符串转换为日期对象? 该字符串是:(对应于格式:) 我不想要datetime.datetime对象,而是想要datetime.date。 问题答案: 您可以在Python包中使用:
问题内容: 我已经写了这个功能: 当我通过日期以及获取输出日期作为 我要去哪里的时候?还做什么,如果我想只得到和 任何帮助表示赞赏 问题答案: 找到以下解决方案…。发布它,因为它也可以帮助其他人:) 输出: 2014-04-24T11:15:00.000 + 02:00
问题内容: 我在这里有点迷路,我认为我一切都很好,但仍然无法正常工作(PaseException 帮助高度赞赏! 问题答案: 对我来说很好。 也许你可以尝试
我有一个日期的字符串格式,但它来自csv文件:20200520T0200,假设它的格式为(yyyyMMdd/T/24小时格式)。 我已经设法读取了csv文件中的行,并将其分离到数组缓冲区中。 我的问题是我不能将字符串格式化成日期,因为我需要使用日期来计算一些值。因为我将使用这个格式化程序来格式化我的arraybuffer的第一个元素的所有值,这是带有字符串“20200406T0300,等等,等等”
我对OffsetDateTime的用法非常陌生,我正在尝试将OffsetDateTime字符串与OffsetDateTime进行比较。以这种方式在java中使用now(), 但我正在学习java。时间总体安排所有3种情况下的DateTimeParseException。 然而,如果我将2个OffsetDateTime字符串与CompareTo方法进行比较,它的工作就很好了。 有没有人能在这方面给我