我应该使用什么 Java DateTime class?
What Java DateTime class should I use?
我们有一个用于生成报告的库。它从数据文件(SQL、XML、JSON 等)中读取,然后可以在用户编写的等式中修改日期时间,然后按照指定的格式进行格式化报告输出。
在等式中的使用可以添加一个时间跨度,获取部分值,如 "if date.month == 2",以及几乎 all the datetime macros in Excel。
因为数据可以是 JSON(或没有架构的 XML),所以日期时间可以是“2019-01-25”、“2019-01-25T14:32:23”、 “2019-01-25T14:32:23.12345”、“2019-01-25T14:32:23Z”或“2019-01-25T14:32:23Z-0500”(最后两个也可以有“.12345”) .
如果没有时区偏移,我们假设日期时间是 UTC。虽然这应该是真的,但通常不是,它是当地时间,但它的使用方式并不重要。因此,除非指定了时区偏移量,否则将其设置为 UTC(到目前为止,我们使用的是 Date)。
第一个问题 - class 我应该用什么来保存这个值?从我读过的内容来看,我认为是 ZonedDateTime,但也许是 Instant?
第二个问题 - 当我必须在日期时间上添加 3 天之类的操作时,我应该使用什么 class 作为时间跨度?
第三个问题 - 是否有一些解析器可以解析我上面列出的所有不同字符串?或者我是否需要调用 String.contains() 来确定格式,然后基于该格式执行显式模式?如果是这样,使用什么 class?
关于第二个问题:是的,JavaJDK中有一个"timespan"class。
对于未附加到时间轴的时间跨度:
Period
表示days/weeks/months/years个数。可用于日期计算,自动计算夏令时 (DST)。
例如,要从给定日期减去 3 天,您可以这样做
ZonedDateTime threeDaysAgo = Period.ofDays(-3).addTo(ZonedDateTime.now());
Duration
与 Period
类似,但以天为单位(以 24 小时为单位,而不是日历日)、小时、分钟、秒和小数秒。
ChronoUnit
如果你需要在更大范围内进行计算(比如包括 hours/minutes/secods 等)还有 ChronoUnit
枚举:
ZonedDateTime threeHoursAgo = ChronoUnit.HOURS.addTo(ZonedDateTime.now(), -3);
Third question - is there some parser that can parse all the different strings as I listed above? Or do I need to call String.contains() to determine the format and then do an explicit pattern based on that? And if so, using what class?
我可能错得很厉害,但是你能在模式和 parseBest 方法上使用带有可选部分的 DateTimeFormatter
吗:
List<String> dates = List.of(
"2019-01-25",
"2019-01-25T14:32:23",
"2019-01-25T14:32:23.12345",
"2019-01-25T14:32:23Z",
"2019-01-25T14:32:23Z-0500"
);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"yyyy-MM-dd['T'[HH:mm:ss][.SSSSS]][z][x]"
); // all the possible combinations
dates.forEach( date -> {
TemporalAccessor accessor = formatter.parseBest(date,
OffsetDateTime::from, // going from most specific date
LocalDateTime::from,
LocalDate::from); // to the less specific
System.out.println( accessor.getClass() + " " + accessor);
}
);
// output for this is
class java.time.LocalDate 2019-01-25
class java.time.LocalDateTime 2019-01-25T14:32:23
class java.time.LocalDateTime 2019-01-25T14:32:23.123450
class java.time.OffsetDateTime 2019-01-25T14:32:23Z
class java.time.OffsetDateTime 2019-01-25T14:32:23-05:00
我们有一个用于生成报告的库。它从数据文件(SQL、XML、JSON 等)中读取,然后可以在用户编写的等式中修改日期时间,然后按照指定的格式进行格式化报告输出。
在等式中的使用可以添加一个时间跨度,获取部分值,如 "if date.month == 2",以及几乎 all the datetime macros in Excel。
因为数据可以是 JSON(或没有架构的 XML),所以日期时间可以是“2019-01-25”、“2019-01-25T14:32:23”、 “2019-01-25T14:32:23.12345”、“2019-01-25T14:32:23Z”或“2019-01-25T14:32:23Z-0500”(最后两个也可以有“.12345”) .
如果没有时区偏移,我们假设日期时间是 UTC。虽然这应该是真的,但通常不是,它是当地时间,但它的使用方式并不重要。因此,除非指定了时区偏移量,否则将其设置为 UTC(到目前为止,我们使用的是 Date)。
第一个问题 - class 我应该用什么来保存这个值?从我读过的内容来看,我认为是 ZonedDateTime,但也许是 Instant?
第二个问题 - 当我必须在日期时间上添加 3 天之类的操作时,我应该使用什么 class 作为时间跨度?
第三个问题 - 是否有一些解析器可以解析我上面列出的所有不同字符串?或者我是否需要调用 String.contains() 来确定格式,然后基于该格式执行显式模式?如果是这样,使用什么 class?
关于第二个问题:是的,JavaJDK中有一个"timespan"class。
对于未附加到时间轴的时间跨度:
Period
表示days/weeks/months/years个数。可用于日期计算,自动计算夏令时 (DST)。
例如,要从给定日期减去 3 天,您可以这样做
ZonedDateTime threeDaysAgo = Period.ofDays(-3).addTo(ZonedDateTime.now());
Duration
与 Period
类似,但以天为单位(以 24 小时为单位,而不是日历日)、小时、分钟、秒和小数秒。
ChronoUnit
如果你需要在更大范围内进行计算(比如包括 hours/minutes/secods 等)还有 ChronoUnit
枚举:
ZonedDateTime threeHoursAgo = ChronoUnit.HOURS.addTo(ZonedDateTime.now(), -3);
Third question - is there some parser that can parse all the different strings as I listed above? Or do I need to call String.contains() to determine the format and then do an explicit pattern based on that? And if so, using what class?
我可能错得很厉害,但是你能在模式和 parseBest 方法上使用带有可选部分的 DateTimeFormatter
吗:
List<String> dates = List.of(
"2019-01-25",
"2019-01-25T14:32:23",
"2019-01-25T14:32:23.12345",
"2019-01-25T14:32:23Z",
"2019-01-25T14:32:23Z-0500"
);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"yyyy-MM-dd['T'[HH:mm:ss][.SSSSS]][z][x]"
); // all the possible combinations
dates.forEach( date -> {
TemporalAccessor accessor = formatter.parseBest(date,
OffsetDateTime::from, // going from most specific date
LocalDateTime::from,
LocalDate::from); // to the less specific
System.out.println( accessor.getClass() + " " + accessor);
}
);
// output for this is
class java.time.LocalDate 2019-01-25
class java.time.LocalDateTime 2019-01-25T14:32:23
class java.time.LocalDateTime 2019-01-25T14:32:23.123450
class java.time.OffsetDateTime 2019-01-25T14:32:23Z
class java.time.OffsetDateTime 2019-01-25T14:32:23-05:00