将 localDate 与 UTC 一起使用
Using localDate with UTC
我在使用 UTC 中的 LocalDate 时遇到问题。我的服务器使用 UTC,我的数据库使用 UTC。我使用 LocalDate 为基于订阅的应用程序存储 billingDate。
发生的情况是我们在午夜 UTC 计费(当进行像 billingDate <= LocalDate.now() 这样的比较时)。我们实际上是想在太平洋标准时间午夜后的某个时间结算。
我真的觉得在这里使用 LocalDate 是合适的,因为我们只想在当天的某个时间点计费。但是,直接在代码或数据库中进行比较时似乎并不实用 (billing_date <= CURRENT_DATE())。我弄错了吗,这应该是 PST 中的 ZonedDateTime 吗?或者我们应该转换为 ZonedDateTime 进行比较?感觉容易出错,我们需要记住每次进行比较时都要转换,但也许这是正确的解决方案?
有没有人遇到过这种情况并找到了好的解决方案?
我看过这个问题,但它没有回答我的问题:Spring REST LocalDate UTC differs of one day
我觉得你应该使用 Instant
s。
I really felt like using LocalDate was appropriate here, because we just want to bill at some point during that day.
嗯,不。您确实关心您的计费时间,因为您的数据库关心时间。它将计费时间存储为 00:00 UTC。因为那是一个瞬间,所以我认为Instant
在这里是最合适的选择。您也可以使用 ZonedDateTime
,但考虑到您可能从数据库中获取 java.sql.Date
,它已经有 toInstant
方法,使用 Instant
s 更方便.
您可以像这样从年月日中获取瞬间:
LocalDate ld = LocalDate.of(2019, 7, 8);
Instant i = ld.atStartOfDay(ZoneId.of("America/Los_Angeles")).toInstant();
America/Los_Angeles
是太平洋标准时间。
我建议这只是将所需时区传递给 LocalDate.now(ZoneId)
的问题。
- 菲律宾标准时间使用
LocalDate.now(ZoneId.of("Asia/Manila"))
。目前它产生 2019-07-09.
- 皮特凯恩标准时间使用
LocalDate.now(ZoneId.of("Pacific/Pitcairn"))
。刚刚给了2019-07-08.
我假设您指的不是太平洋标准时间,因为在我们说话时没有时区使用太平洋标准时间(那些在冬天使用的时区现在是太平洋夏令时)。无论如何,请注意三个字母的时区缩写通常是模棱两可的。
具有now
方法的java.time类通常具有三个重载变体:
- 采用我推荐的
ZoneId
个参数供一般使用。
- 一个采用
Clock
参数的方法非常适合可测试性。 Clock
包括一个时区,所以这个也能为您提供指定时区的当前日期 and/or 时间。
- 一个不接受任何参数并使用 JVM 的默认时区。我建议您永远不要使用它。很高兴 reader 知道您已经考虑了时区并选择了您想要的时区。并且默认时区可以由同一 JVM 中的任何程序随时更改 运行,因此不够稳定以依赖于实际工作。
我在使用 UTC 中的 LocalDate 时遇到问题。我的服务器使用 UTC,我的数据库使用 UTC。我使用 LocalDate 为基于订阅的应用程序存储 billingDate。
发生的情况是我们在午夜 UTC 计费(当进行像 billingDate <= LocalDate.now() 这样的比较时)。我们实际上是想在太平洋标准时间午夜后的某个时间结算。
我真的觉得在这里使用 LocalDate 是合适的,因为我们只想在当天的某个时间点计费。但是,直接在代码或数据库中进行比较时似乎并不实用 (billing_date <= CURRENT_DATE())。我弄错了吗,这应该是 PST 中的 ZonedDateTime 吗?或者我们应该转换为 ZonedDateTime 进行比较?感觉容易出错,我们需要记住每次进行比较时都要转换,但也许这是正确的解决方案?
有没有人遇到过这种情况并找到了好的解决方案?
我看过这个问题,但它没有回答我的问题:Spring REST LocalDate UTC differs of one day
我觉得你应该使用 Instant
s。
I really felt like using LocalDate was appropriate here, because we just want to bill at some point during that day.
嗯,不。您确实关心您的计费时间,因为您的数据库关心时间。它将计费时间存储为 00:00 UTC。因为那是一个瞬间,所以我认为Instant
在这里是最合适的选择。您也可以使用 ZonedDateTime
,但考虑到您可能从数据库中获取 java.sql.Date
,它已经有 toInstant
方法,使用 Instant
s 更方便.
您可以像这样从年月日中获取瞬间:
LocalDate ld = LocalDate.of(2019, 7, 8);
Instant i = ld.atStartOfDay(ZoneId.of("America/Los_Angeles")).toInstant();
America/Los_Angeles
是太平洋标准时间。
我建议这只是将所需时区传递给 LocalDate.now(ZoneId)
的问题。
- 菲律宾标准时间使用
LocalDate.now(ZoneId.of("Asia/Manila"))
。目前它产生 2019-07-09. - 皮特凯恩标准时间使用
LocalDate.now(ZoneId.of("Pacific/Pitcairn"))
。刚刚给了2019-07-08.
我假设您指的不是太平洋标准时间,因为在我们说话时没有时区使用太平洋标准时间(那些在冬天使用的时区现在是太平洋夏令时)。无论如何,请注意三个字母的时区缩写通常是模棱两可的。
具有now
方法的java.time类通常具有三个重载变体:
- 采用我推荐的
ZoneId
个参数供一般使用。 - 一个采用
Clock
参数的方法非常适合可测试性。Clock
包括一个时区,所以这个也能为您提供指定时区的当前日期 and/or 时间。 - 一个不接受任何参数并使用 JVM 的默认时区。我建议您永远不要使用它。很高兴 reader 知道您已经考虑了时区并选择了您想要的时区。并且默认时区可以由同一 JVM 中的任何程序随时更改 运行,因此不够稳定以依赖于实际工作。