自 1989 年 12 月 31 日上午 12:00 以来的秒数 Java

Seconds since 12:00 am December 31, 1989 Java

我必须计算从 12:00 1989 年 12 月 31 日到现在的秒数。 第二个解析器来自 Garmin Fleet Management。 这是我的代码:

public int getDate(){
    Date d1 = new Date(1989, 12, 31, 12, 0, 0);
    Date today = new Date();
    long diff = today.getTime() - d1.getTime();
    return (int)(diff/1000);
}

Garmin 解析器中 getDate() 的秒数显示为 2021 年 7 月 28 日下午 08:35,而不是现在。

这是我需要的日期时间的解释(通过文档)

It is an unsigned 32-bit integer and its value is the number of seconds since 12:00 am December 31, 1989, UTC.

我哪里弄错了?

您应该 return long 并将您的差异包装到 Math.abs() 以获得表达差异的积极结果。

public static long getDate() {
    Date d1 = new Date(1989, 12, 31, 12, 0, 0);
    Date today = new Date();
    long diff = Math.abs(today.getTime() - d1.getTime());
    return (diff/1000);
}

Java中没有unsigned


此外 Date 的构造函数已过时,因此使用 Calendar 是更好的方法:

public static long getDate() {
    Calendar d1 = new GregorianCalendar(1989, 11, 31, 0, 0, 0);
    Date today = new Date();
    long diff = Math.abs(today.getTime() - d1.getTime().getTime());
    return (diff/1000);
}

您应该使用 Calendar 实例而不是 Date 构造函数已弃用:

public static long getDate(){
    Calendar calendar = new GregorianCalendar(1989, 11, 31, 0, 0, 0);
    Date today = new Date();

    long diff = today.getTime() - calendar.getTime().getTime();
    return diff / 1000;
}

Date 构造函数接受 year 作为 (current year value - 1900) 格式。通过 Javadoc:

  • @param year the year minus 1900.
    • @param month the month between 0-11.
    • @param date the day of the month between 1-31.
    • @see java.util.Calendar
    • @deprecated As of JDK version 1.1,
    • replaced by Calendar.set(year + 1900, month, date)
    • or GregorianCalendar(year + 1900, month, date).

你还应该使用long(Java中没有unsigned int)return值

您使用的是已弃用的 API。年份参数不是直接年份,而是从 1900 年开始的年数。

@已弃用 public日期(整数年, 整月, 内部日期, 内部小时, 分钟) 已弃用。从 JDK 版本 1.1 开始,替换为 Calendar.set(年 + 1900、月、日、时、分) 或 GregorianCalendar(年 + 1900、月、日、时、分)。 分配一个 Date 对象并对其进行初始化,使其代表本地时区中由年、月、日、hrs 和 min 参数指定的分钟开始时刻。 参数: year - 年份减去 1900。

tl;博士

Duration.between(                              // Represent a span-of-time unattached to the timeline.
    Instant.parse( "1989-12-31T00:00:00Z" ) ,  // Garmin epoch reference date.
    Instant.now()                              // Capture the current moment in UTC. 
)                                              // Returns a `Duration` object.
.toSeconds()                                   // This span-of-time as a total number of whole seconds. Beware of data loss: Any fractional second is ignored.

详情

其他答案使用过时的类。

java.time

Java 8 及更高版本内置了 java.time 框架。替代旧的麻烦的日期时间 类 例如 java.util.Date & .Calendar.

long 对比 int

正如其他人提到的,Java 没有无符号整数——只有符号。所以这里我们使用 64 位 long 而不是 32 位 int。 Java 8 允许您对 int 值执行一些操作,同时 假装 它们是无符号的,但我们实际上没有无符号的 int 类型。请参阅另一个问题 Declaring an unsigned int in java,了解更多信息,包括为 Google Guava 等库中的无符号整数设计的几个 类。

Instant

在 java.time 中,Instant is a moment on the timeline in UTC. A Duration 表示一个时间跨度,表示为总秒数加上秒的小数部分(纳秒)。

当天的第一刻

不确定“1989 年 12 月 31 日凌晨 12:00 UTC”是指一天的第一刻 (00:00:00.0) 还是一天的结束。我将第一时间作为 epoch. Indeed, this PDF document Garmin Device Interface Specification,据称由 Garmin 于 2004 年 9 月 16 日发布,声明:

7.3.14 time_type

The time_type is used in some data structures to indicate an absolute time. It is an unsigned 32 bit integer and its value is the number of seconds since 12:00 am December 31, 1989 UTC.

代码。

Instant garminEpoch = Instant.parse( "1989-12-31T00:00:00Z" );
Instant now = Instant.now();
Duration duration = Duration.between( garminEpoch , now );
long seconds = duration.getSeconds(); // This span of time as a total number of seconds.

关于java.time

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.

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

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 类.

在哪里获取java.time类?

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.

我也无意中发现了 Garmin 的问题,我认为你弄错了日期:'12:00 am December 31, 1989' 是 midnight 从 30 日到31 日,或者用军事术语来说就是 31 日的“零百小时”,0:00h 对世界其他地方来说!你把它当作 中午 时间!

这次参考来自“Garmin 设备接口规范,2006 年 5 月 19 日,图号:001-00063-00 Rev. C”,其中写着:

7.3.14 time_type

The time_type is used in some data structures to indicate an absolute time. It is an unsigned 32 bit integer and its value is the number of seconds since 12:00 am December 31, 1989 UTC.

我不确定这是 Garmin-specific 还是典型的 GPS 设备时间问题,因为 GPS 时间很重要,例如闰秒分开。至少在 Garmin 记录中,UTC 时间需要从以下内容构造: 1. 上述参考日期 2.闰秒(2018年=18) 3. 拖车(从星期日算起的一周中的时间 0:00h) 4. 和wn_days(周数天数)

总的来说,我的 Python3 结构是:

tref        = time.mktime((1989, 12, 31,  0,  0,  0, 0, 0, -1))                                     
tsec        = tref + wn_days * 86400. + tow - leap_scnds                                            
pvttime     = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tsec)) 
# result: e.g. 2018-02-22 15:09:49 UTC

这给了我正确的 UTC 时间。