按天对长 UTC 日期进行分组

发布于 2024-07-15 20:21:57 字数 175 浏览 9 评论 0 原文

有没有一种明智的方法可以按天对长 UTC 日期进行分组?

我会将它们修改为 86400,但这没有考虑闰秒。

有没有人有任何其他想法,我正在使用 java,所以我可以将它们解析为日期对象,但我有点担心使用日期类的性能开销。

还有比比较 Date 对象的年月日部分更有效的方法吗?

Is there a sensible way to group Long UTC dates by Day?

I would Mod them by 86400 but that doesn't take leap seconds into account.

Does anyone have any other ideas, I'm using java so I could parse them into Date Objects, but I'm a little worried of the performance overhead of using the date class.

Also is there a more efficient way than comparing the year month and day parts of a Date object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

他不在意 2024-07-22 20:21:57

您的源数据肯定首先包含闰秒吗? 有些 API 可以,有些则不行 - Joda Time(我推荐使用内置日期/时间 API)不使用闰秒。 Java 日期和时间 API“有时”会这样做 - 它们支持 60 和 61 作为“分钟秒”值,但支持取决于操作系统(见下文)。 如果您有一些好的样本值,如果我是您,我会先检查一下。 显然,仅仅划分比其他任何事情都要简单。

如果您确实需要创建Date对象(或Joda中的DateTime),我会在做其他事情之前对其进行基准测试。 您可能会发现性能实际上已经足够了。 浪费时间优化适合您的数据的东西是没有意义的。 当然,您首先需要确定需要支持的数据大小,以及需要多快的速度:)

即使 java.util.Date 对闰秒的支持也有些不确定。 来自文档

尽管 Date 类的目的是
反映协调世界时
(UTC),它可能不完全如此,
取决于宿主环境
Java 虚拟机。 几乎所有
现代操作系统假设 1
天 = 24 × 60 × 60 = 86400 秒
所有情况。 然而,在 UTC 中,大约有一次
每一两年都会有一个额外的
第二个,称为“闰秒”。 这
闰秒始终添加为
一天的最后一秒,并且始终开启
12 月 31 日或 6 月 30 日。例如,
1995年的最后一刻是
61 秒长,感谢添加
闰秒。 大多数计算机时钟是
不够准确,无法
反映闰秒的区别。

有一篇关于相当不错的博客文章 Java 和闰秒的混乱,您可能也想阅读。

Does your source data definitely include leap seconds to start with? Some APIs do, and some don't - Joda Time (which I'd recommend over the built-in date/time APIs) doesn't use leap seconds, for example. The Java date and time APIs "sometimes" do - they support 60 and 61 as values of "second in minute" but support depends on the operating system (see below). If you have some good sample values, I'd check that first if I were you. Obviously just dividing is rather simpler than anything else.

If you do need to create Date objects (or DateTime in Joda) I would benchmark it before doing anything else. You may well find that the performance is actually perfectly adequate. There's no point in wasting time optimizing something which is okay for your data. Of course, you'll need to decide data size you need to support, and how quick it needs to be first :)

Even the java.util.Date support for leap seconds is somewhat indeterminate. From the docs:

Although the Date class is intended to
reflect coordinated universal time
(UTC), it may not do so exactly,
depending on the host environment of
the Java Virtual Machine. Nearly all
modern operating systems assume that 1
day = 24 × 60 × 60 = 86400 seconds in
all cases. In UTC, however, about once
every year or two there is an extra
second, called a "leap second." The
leap second is always added as the
last second of the day, and always on
December 31 or June 30. For example,
the last minute of the year 1995 was
61 seconds long, thanks to an added
leap second. Most computer clocks are
not accurate enough to be able to
reflect the leap-second distinction.

There's a rather good blog post about the mess with Java and leap seconds which you may want to read too.

自在安然 2024-07-22 20:21:57

我会将它们修改为 86400,但这并没有考虑闰秒......

我很确定那会很好。 Date 的 API 文档确实不应该包含任何有关闰秒的内容,因为事实上它模拟了一个标准的 Unix 时间标记,而该时间标记的值中不包含闰秒。
相反,它的作用是通过在闰秒开始时将股票代码值向后设置 1 秒(如上一篇文章中的链接所述),使第 59 秒持续两秒。

因此,您可以假设从 Date.getTime() 获得的值仅由 86400 秒的天组成。 如果您确实需要知道特定一天是否有闰秒,互联网上有几个可用的表格(自 1972 年以来只有 23-24 个表格,在此之前的计算机日期很少将它们考虑在内)无论如何帐户)。

你好

温斯顿

I would Mod them by 86400 but that doesn't take leap seconds into account....

I'm pretty sure that that will be fine. The API documentation for Date really shouldn't include anything about leap seconds, because the fact is that it emulates a standard Unix time ticker which does NOT include leap seconds in its value.
What it does instead is to have a 59th second that lasts for two seconds by setting the ticker value back by 1 second at the start of a leap second (as the link in the previous post describes).

Therefore you can assume that the value you get from Date.getTime() IS made up only of 86400-second days. If you really need to know whether a particular day had a leap second, there are several tables available on the Internet (there have only been 23-24 since 1972, and computer dates before that rarely took them into account anyway).

HIH

Winston

笑饮青盏花 2024-07-22 20:21:57

tl;dr

Instant.ofEpochSecond( 1_493_367_302L )            // Convert a count of whole seconds from epoch of 1970 into a date-time value in UTC.
       .atZone( ZoneId.of( "Pacific/Auckland" ) )  // Adjust into the time zone as a context for determining a date.
       .toLocalDate()                              // Extract a date-only value by which we can sort/collect/organize our date-time values.

时区

java.util.Date 类表示 UTC 时间轴上的某个时刻。 因此,询问它的日期会得到一个仅在 UTC 中有意义的日期。 同一时刻可能是魁北克的较早日期或新西兰奥克兰的较晚日期。

时区对于确定日期至关重要,而您的问题忽略了这个问题。

使用 java.time

java.util.Date 类是麻烦的旧日期时间类的一部分,这些旧日期时间类现在已被遗留下来,并被 java.time 类取代。

至于闰秒,正如其他答案所建议的那样,大多数纪元计数来源都不计算闰秒。 因此请验证您的来源。

如果您有从 1970-01-01T00:00:00 纪元开始的整秒计数,则使用静态方法创建一个 Instant 对象。

Instant instant = Instant.ofEpochSecond( 1_493_367_302L ) ;

instant.toString(): 2017-04-28T08:15:02Z

分配一个时区来创建我们可以确定日期的上下文。 对于任何特定时刻,世界各地的日期因地区而异。

大陆/地区格式指定正确的时区名称 ,例如 America/Montreal非洲/卡萨布兰卡,或太平洋/奥克兰 。 切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的( !)。

ZoneId z = ZoneId.of( "America/Montreal" ); 
ZonedDateTime zdt = instant.atZone( z );

zdt.toString(): 2017-04-28T01:15:02-07:00[美国/洛杉矶]

通过这些 ZonedDateDate 对象,您可以按日期进行比较。 您可以提取 LocalDate 对象。 LocalDate 类表示仅日期值,没有时间和时区。

LocalDate ld = zdt.toLocalDate();

ld.toString(): 2017-04-28

所以你可以用 LocalDate 作为键和 List 制作一个 MapZonedDateTime 对象的 设置为值。 通过现代 lambda 语法,您可以使用 Streams 来执行该映射。


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,例如java.util.Date, 日历, & ; SimpleDateFormat

Joda-Time 项目,现已在 维护模式,建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。 并在 Stack Overflow 上搜索许多示例和解释。 规范为 JSR 310

从哪里获取 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time 。 该项目是 java.time 未来可能添加的内容的试验场。 您可能会在这里找到一些有用的类,例如 间隔YearWeek<代码>YearQuarter,以及更多

tl;dr

Instant.ofEpochSecond( 1_493_367_302L )            // Convert a count of whole seconds from epoch of 1970 into a date-time value in UTC.
       .atZone( ZoneId.of( "Pacific/Auckland" ) )  // Adjust into the time zone as a context for determining a date.
       .toLocalDate()                              // Extract a date-only value by which we can sort/collect/organize our date-time values.

Time zone

The java.util.Date class represents a moment on the timeline in UTC. So asking it for a date gets you a date that only makes sense in UTC. That very same moment may be a date earlier in Québec or a date later in Auckland, New Zealand.

Time zone is crucial in determining a date, and your Question ignores this issue.

Using java.time

The java.util.Date class is part of the troublesome old date-time classes that are now legacy, supplanted by the java.time classes.

As for leap seconds, as the other Answers suggested, most sources of count-from-epoch do not count leap seconds. So verify your source.

If you have a count of whole seconds from epoch of 1970-01-01T00:00:00, then use the static method to create a Instant object.

Instant instant = Instant.ofEpochSecond( 1_493_367_302L ) ;

instant.toString(): 2017-04-28T08:15:02Z

Assign a time zone to create the context in which we can determine a date. For any given moment, the date varies around the world by zone.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" ); 
ZonedDateTime zdt = instant.atZone( z );

zdt.toString(): 2017-04-28T01:15:02-07:00[America/Los_Angeles]

With of bunch of these ZonedDateDate objects, you can compare by date. You can extract a LocalDate object. The LocalDate class represents a date-only value without time-of-day and without time zone.

LocalDate ld = zdt.toLocalDate();

ld.toString(): 2017-04-28

So you could make a Map with LocalDate as the key and an List or Set of ZonedDateTime objects as the value. And with the modern lambda syntax, you could use Streams to do that mapping.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文