San*_*pat 1 java time spring datetime date
我试图获取特定时区特定月份的开始和结束时间,特别是“亚洲/加尔各答”(UTC+05:30)。
例如,以下是 2023 年 9 月的开始和结束时间。
开始时间: 2023-09-01 00:00:00
结束时间: 2023-09-30 23:59:59
我用Java实现了以下功能:
public static Long getStartTimeStampOfMonth(Month month, Year year) {
LocalDate startDate = LocalDate.of(year.getValue(), month, 1);
LocalDateTime startDateTime = LocalDateTime.of(startDate, LocalTime.MIN);
ZonedDateTime istDateTime = startDateTime.atZone(ZoneId.of("Asia/Kolkata"));
return Timestamp.valueOf(istDateTime.toLocalDateTime()).getTime();
}
public static Long getEndTimeStampOfMonth(Month month, Year year) {
LocalDate startDate = LocalDate.of(year.getValue(), month, 1);
LocalDate endDate = startDate.withDayOfMonth(startDate.lengthOfMonth());
LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.MAX);
ZonedDateTime istDateTime = endDateTime.atZone(ZoneId.of("Asia/Kolkata"));
return Timestamp.valueOf(istDateTime.toLocalDateTime()).getTime();
}
Run Code Online (Sandbox Code Playgroud)
但是,我注意到上面的代码根据计算机上配置的时区返回开始和结束时间。即使我已明确指定 ZoneId.of("Asia/Kolkata"),它也不会产生所需的结果。
当我在设置为 UTC 时区的计算机上测试 2023 年 9 月的代码时,我得到以下输出:
开始时间:1693526400000
结束时间:1696118399999
但是,我希望输出保持一致,无论机器的时区如何:
开始时间:1693506600000
结束时间:1696098599999
请帮助我确定我可能缺少的内容或建议替代方法。
ZonedDateTime当您从 转换为 时,将引入本地时区Timestamp:
return Timestamp.valueOf(istDateTime.toLocalDateTime()).getTime();
Run Code Online (Sandbox Code Playgroud)
由于您正在使用 a LocalDateTime,因此该Timestamp.valueOf方法将假定本地时区。
来自文档:
public static Timestamp valueOf(LocalDateTime dateTime)
Timestamp从对象获取 的实例LocalDateTime,其与提供的 具有相同的年、月、日、时、分、秒和纳秒日期时间值LocalDateTime。提供的
LocalDateTime被解释为当地时区的当地日期时间。
Timestamp相反,您可以从以下位置创建Instant:
return Timestamp.from(istDateTime.toInstant()).getTime();
Run Code Online (Sandbox Code Playgroud)
不过,由于您似乎以毫秒long为单位,因此您可以完全跳过该类型:Timestamp
return istDateTime.toInstant().toEpochMilli();
Run Code Online (Sandbox Code Playgroud)
YearMonth\n.of( 2023 , Month.NOVEMBER )\n.atDay( 1 ) \n.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) ) \n.toInstant()\n.toEpochMilli()\nRun Code Online (Sandbox Code Playgroud)\n\xe2\x80\xa6 和:
\nYearMonth\n.of( 2023 , Month.NOVEMBER )\n.plusMonths( 1 )\n.atDay( 1 ) \n.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) ) \n.toInstant()\n.toEpochMilli()\nRun Code Online (Sandbox Code Playgroud)\n\n\n2023 年 9 月
\n
使用java.time.YearMonthclass 代表月份。
YearMonth ym = YearMonth.of( 2023 , Month.NOVEMBER ) ;\nRun Code Online (Sandbox Code Playgroud)\n\n\n特定时区特定月份的开始和结束时间,特别是“亚洲/加尔各答”(UTC+05:30)。
\n
首先获取日期。
\nYearMonth\n.of( 2023 , Month.NOVEMBER )\n.atDay( 1 ) \n.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) ) \n.toInstant()\n.toEpochMilli()\nRun Code Online (Sandbox Code Playgroud)\n获得第一天的第一个时刻。这样做需要时区。不要假设一天从 00:00 开始,因为某些区域的某些日期可能在其他时间开始,例如 01:00。让java.time确定一天中的第一个时刻。
\nYearMonth\n.of( 2023 , Month.NOVEMBER )\n.plusMonths( 1 )\n.atDay( 1 ) \n.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) ) \n.toInstant()\n.toEpochMilli()\nRun Code Online (Sandbox Code Playgroud)\n\n\n结束时间: 2023-09-30 23:59:59
\n
你的例子不正确。如果你的月经临近,你就会错过最后一天的最后一秒。
\n最好将您的时间跨度定义为半开放式,其中开始是包容性的,而结束是排他性的。因此,一个月从第一天的第一时刻开始,一直到(但不包括)下个月的第一时刻。使用这种安排,您将不会失去最后一秒。
\nZonedDateTime endZdt = endDate.plusDays ( 1 ).atStartOfDay ( z );\nRun Code Online (Sandbox Code Playgroud)\n显然,您希望将这两个时刻表示为自 UTC 1970-01-01T00:00Z 中看到的 1970 年第一个时刻的纪元参考以来的毫秒数。
\n您尝试获取该计数\xe2\x80\xa6
\nTimestamp.valueOf(istDateTime.toLocalDateTime()).getTime();\nRun Code Online (Sandbox Code Playgroud)\n\xe2\x80\xa6 在两个方面是不正确的:
\ntoLocalDateTime丢失了任何时区或与 UTC 的偏移量的概念。LocalDateTime处理时刻时不要使用物体。有关更多解释,请参阅Johnson-Pint 的正确答案。Timestamp,该类多年前已被 JSR 310 中定义的现代java.time类取代。避免使用遗留类,仅使用java.time类。要将我们的两个时刻调整为距 UTC 时间子午线零小时-分钟-秒的偏移,请提取Instant对象。
YearMonth ym = YearMonth.of( 2023 , Month.NOVEMBER ) ;\nRun Code Online (Sandbox Code Playgroud)\n从那里你可以得到毫秒数。
\nLocalDate startDate = ym.atDay ( 1 );\nLocalDate endDate = ym.atEndOfMonth ( );\nRun Code Online (Sandbox Code Playgroud)\n我不建议您以这种方式表现时刻。毫秒计数是不明确的,因为它只是一个没有上下文的整数,这会产生歧义。1970-01-01T00:00Z 只是数十个常见纪元引用之一。此外,人类无法破译纪元的计数。这意味着错误很容易被忽视。
\n我建议您使用标准ISO 8601格式以文本方式传达日期时间值。在 UTC 中,一个例子是2023-10-02T20:53:59Z. 将T日期部分与时间部分分开。这Z是一个缩写+00:00,偏移量为零。
这是一个完整的代码示例。
\nZoneId z = ZoneId.of ( "Asia/Kolkata" );\nZonedDateTime startZdt = startDate.atStartOfDay ( z );\nRun Code Online (Sandbox Code Playgroud)\n运行时:
\nZonedDateTime endZdt = endDate.plusDays ( 1 ).atStartOfDay ( z );\nRun Code Online (Sandbox Code Playgroud)\n要处理成对的时刻,我建议将ThreeTen-Extra库添加到您的项目中。该库包含该类Interval,以将一段时间表示为一对Instant对象。该类提供了几种方便的方法,例如contains、abuts和intersection。该类解析/生成标准 ISO 8601 格式的文本,其中两个时刻用斜杠分隔。
Interval monthInterval = Interval.of( startInstant , endInstant ) ;\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
133 次 |
| 最近记录: |