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

时间:2018-08-07 12:57:53

标签: java date simpledateformat epoch

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

但是我收到的秒数不是从UNIX时代01/01/1970开始而是2000年1月1日。

通常我会使用:

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

将millisConvert转换为我收到的毫秒数。但是现在,自然而然地,我会得出错误的日期,因为出处不同。如何更改纪元(原点)?

3 个答案:

答案 0 :(得分:2)

tl; dr

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 类代替了可怕的旧遗留类,例如DateCalendar

Instant

Instant代表UTC的时刻。

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

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

添加您的秒数。

Instant later = epoch.plusSeconds( yourSecondsGoHere ) ; 

OffsetDateTime

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

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

LocalDate

提取仅日期值。

LocalDate ld = odt.toLocalDate() ;

关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

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

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

答案 1 :(得分:1)

加上946080000秒来解决30年的差异,纪元时间应该是长值

答案 2 :(得分:0)

与Basil建议的答案不同的另一种方法。 Basil建议的内容仅适用于API级别26及更高版本,即Android 8.0.0。如今,在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;
            }

        }

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