使用Java将Unix时代转换为人类可读的日期不正确

问题描述 投票:1回答:2

编辑:删除了'* 1000'并仍然得到不正确的日期,但更新了下面的日志以显示我现在得到的内容。

下面是我的代码段和日志,我以为我正确实现了它,所以我不知道为什么它没有给我正确的转换:

NewFoodItem foodItem = data.get(position);
String date = new java.text.SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(new java.util.Date (foodItem.date));
String a =  Integer.toString(foodItem.date);
Log.d("returnedDate:", a);
Log.d("formattedDate:", date);

它不会让我发布图像,但是日志看起来像这样:

D/returnedDate:  1409012824
D/formattedDate: 01/17/1970 02:23:32
D/returnedDate:  1409013004
D/formattedDate: 01/17/1970 02:23:33
java android epoch
2个回答
2
投票

我刚刚进行了一些假设的测试,看来问题与整数溢出有关。

我假设您将NewFoodItem.date定义为int,而不是long。因此,当您乘以date * 1000(均为int)时,它将返回int

int d = 1409012824; // foodItem.date
int d1000 = d * 1000; // returns 263550912 because of overflow, instead of 1409012824000

String date = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss")
    .format(new Date(d1000)); // returns 01/04/1970 08:42:30

[当我尝试将其中之一更改为long时,它的行为符合预期

// case 1
long d = 1409012824;
long d1000 = d * 1000; // now returns 1409012824000 correctly

String date = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss")
    .format(new Date(d1000)); // returns 08/26/2014 08:27:04

// case 2
int d = 1409012824;
long d1000 = d * 1000L; // note the "L" suffix to indicate the number as long 
long d1000f = d * 1000; // FAIL, still returns 263550912 because of integer overflow

String date = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss")
    .format(new Date(d1000)); // returns 08/26/2014 08:27:04
String date = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss")
    .format(new Date(d1000f)); // returns 01/04/1970 08:42:30

[通常,在Java中使用Date时,我们将它们定义为long,因为它们通常以毫秒为单位。为了便于维护,最好将NewFoodItem.date的类型更改为long。如果也是毫秒也更好。


0
投票

Answer by Andrew T.是正确的:整数溢出。但是示例代码现在已过时。

java.time

现代方法使用java.time类。

Instant类表示一个时刻。像java.util.Date一样,Instant从UTC 1970-01-01T00:00Z的1970年第一时刻的epoch reference开始计数。但是Instant使用的是纳秒而不是毫秒的更高分辨率。

L附加到数字文字的末尾以指示long类型。在您希望对数字进行分组的任何地方都使用下划线,并且不添加任何含义(编译器会忽略)。

long input = 1_409_012_824L ;
Instant instant = Instant.ofEpochSecond( input ) ;

以标准ISO 8601格式生成值的文本表示形式。

String output = instant.toString() ;

2014-08-26T00:27:04Z

为了更灵活地生成文本,请转换为OffsetDateTime

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

使用DateTimeFormatter自动定位输出。

DateTimeFormatter

2014年8月26日,上午12:27:04

参见此Locale locale = Locale.US ; DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( locale ) ; String output2 = odt.format( f ) ;


code run live at IdeOne.com


关于java.time

Table of date-time types in Java, both modern and legacy.框架内置于Java 8及更高版本中。这些类取代了麻烦的旧java.time日期时间类,例如legacyjava.util.Datejava.util.Date

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

SimpleDateFormat项目现在位于SimpleDateFormat中,建议迁移到Oracle Tutorial类。

您可以直接与数据库交换java.time

对象。使用兼容JSR 310或更高版本的Joda-Time。不需要字符串,不需要maintenance mode类。

从哪里获取java.time类?

  • Android
  • ThreeTenABP项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如ThreeTen-BackportHow to use ThreeTenABP…Table of which java.time library to use with which version of Java or AndroidThreeTen-Extra

    © www.soinside.com 2019 - 2024. All rights reserved.