如何计算自定义纪元时间?不是 UNIX 时代

How do I make calculation on a custom Epoch time? Not the UNIX epoch

我在 后从服务器接收数据,我想将其转换为日期。

但我收到的秒数不是自 UNIX 纪元 01/01/1970 以来,而是 01/01/2000。

通常我会使用:

SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy", Locale.US);
String dateString = formatter.format(new Date(millisToConvert));

其中 millisConvert 是我收到的转换为毫秒的秒数。但是现在,自然地,我得到了错误的日期,因为来源不同。如何更改纪元(原点)?

添加 946080000 秒来计算 30 年的差异,纪元时间应该是一个 long 值

tl;博士

OffsetDateTime.of( 2000 , 1 , 1 , 0 , 0 , 0 , 0 , ZoneOffset.UTC )  // Define your epoch reference moment. 
.pluSeconds( yourSeconds )  // Add the number of seconds given to you. Returns another `OffsetDateTime` object rather than altering the original (immutable objects pattern).  
.toLocalDate()     // Extract a date-only value without time-of-day and without offset-from-UTC. 

java.time

使用现代 java.time classes 取代可怕的旧遗留 classes,例如 Date & Calendar

Instant

一个 Instant 表示 UTC 中的一个时刻。

定义您的特定纪元参考日期时间。

Instant epoch = Instant.parse( "2000-01-01T00:00Z" ) ;

添加您的秒数。

Instant later = epoch.plusSeconds( yourSecondsGoHere ) ; 

OffsetDateTime

如果您想要一个没有时间和时区的纯日期值,请使用 LocalDate class。首先,从基本类型 Instant 转换为更灵活的 OffsetDateTime,指定常量 ZoneOffset.UTC 作为偏移量。

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;

LocalDate

提取仅日期值。

LocalDate ld = odt.toLocalDate() ;


关于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 classes.

要了解更多信息,请参阅 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.* classes.

从哪里获得java.time classes?

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.

除了我标记为答案的 Basil 建议之外的另一种方式。 Basil 的建议仅适用于 API 级别 26 和更高级别 Android 8.0.0。如今,post-2018 年年中,Android 8.0.0 非常罕见,因此许多设备都没有此功能。

所以我写了这个算法:

private long getDateInMilliSeconds (long secondsSinceRippleEpoch){

        Locale.setDefault(Locale.US);

        if (Build.VERSION.SDK_INT >= 26) { //**WHAT BASIL SUGGESTED**
            LocalDateTime desiredDate = OffsetDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC)
                    .plusSeconds(secondsSinceRippleEpoch)
                    .toLocalDateTime();

            Date convertedDate = Date.from(desiredDate.atZone(ZoneId.systemDefault()).toInstant());

            return convertedDate.getTime();
        } else { //MY SOLUTION. Works for both but still I wanted to use the upper
//for higher APIs.

            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.US);
            String dateString = formatter.format(new Date((secondsSinceRippleEpoch+946684800)*1000L )); //To not to cause overflow, use L at the end.

            try {
                Date wantedDate = formatter.parse(dateString);
                return wantedDate.getTime();
            } catch (ParseException e) {
                e.printStackTrace();
                return 200000;
            }

        }

希望这对未来的访客有所帮助。