Java 在不同时间计算的相同日期的毫秒数确实不同

Java 在不同时间计算的相同日期的毫秒数确实不同,java,android,database,date,time,Java,Android,Database,Date,Time,最近,我尝试将当前日期的毫秒表示形式用作数据库(领域)的主键 我可以将日期作为字符串存储,但由于我需要对大量数据执行快速升序搜索,所以我决定以毫秒格式存储数据 为此,我遵循以下步骤: 1) 初始化GregorianCalendar实例并传递当前日期 Calendar c = new GregorianCalendar(); c.setTime(new Date()); 2) 将时间设置为正好匹配当前一天的午夜 c.set(Calendar.HOUR_OF_DAY,0);

最近,我尝试将当前日期的毫秒表示形式用作数据库(领域)的主键

我可以将日期作为字符串存储,但由于我需要对大量数据执行快速升序搜索,所以我决定以毫秒格式存储数据

为此,我遵循以下步骤:

1) 初始化GregorianCalendar实例并传递当前日期

    Calendar c = new GregorianCalendar();
    c.setTime(new Date());
2) 将时间设置为正好匹配当前一天的午夜

    c.set(Calendar.HOUR_OF_DAY,0);
    c.set(Calendar.MINUTE,0);
    c.set(Calendar.SECOND,0);
    c.set(Calendar.MILLISECOND,0);
3) 将结果转换为毫秒

    c.getTime().getTime()
后来,我通过将对象插入数据库来测试它。 下面是日志输出。我计算了几次相同的日期,都是根据上面的代码,没有任何变化

01-03 06:59:38.607 16256-16256/com.example.bizarre.bindaccess D/Day: Long: 1 422 528 534 032 Date: 29.01.15
01-03 06:59:38.611 16256-16256/com.example.bizarre.bindaccess D/Day: Long: 1 422 528 647 420 Date: 29.01.15
01-03 06:59:38.611 16256-16256/com.example.bizarre.bindaccess D/Day: Long: 1 422 528 669 794 Date: 29.01.15
01-03 06:59:38.611 16256-16256/com.example.bizarre.bindaccess D/Day: Long: 1 422 528 707 566 Date: 29.01.15
01-03 06:59:38.615 16256-16256/com.example.bizarre.bindaccess D/Day: Long: 1 422 532 686 557 Date: 29.01.15
01-03 06:59:38.615 16256-16256/com.example.bizarre.bindaccess D/Day: Long: 1 422 532 726 052 Date: 29.01.15
01-03 06:59:38.615 16256-16256/com.example.bizarre.bindaccess D/Day: Long: 1 422 532 754 147 Date: 29.01.15
尽管我的动作是零小时、分钟、秒和毫秒,但到那时,我每次得到的值都会有一个以毫秒为单位的清除午夜值

我的建议是:

1) 这取决于设备时间方案

2) 它本身与安卓系统有关

3) 麻烦就在我这边

如果有人能帮我,我会很高兴的

p.S.I还使用了一个站点,得到了29.01.15的毫秒数,结果是1422 489 600 000

更新了#1。1) 所有的插入都在同一个设备上,本地时区并没有改变,所以环境无论如何都不会受到影响。 2) 正如我上面所说的,可能不清楚-我将数据保存在long类型的类字段中的millis。这一领域也不会受到任何影响

已更新#2。事实上,我的问题是:“我遇到的行为如何解释?”。但由于它可能太宽或不清楚,我将重点放在我最初想要实现的目标上-“如何以一致的毫秒值(长类型)的形式获取本地(设备上)时区的当前日期”

tl;博士 2015-01-29T00:00:00Z

你的问题? 虽然不清楚,但我会将您的问题解释为:如何从历元数中进行计数,并将其更改为表示UTC中该日期的00:00:00时间

“如何以一致的毫秒值(long类型)的形式获取本地(设备上)时区中的当前日期?”

从大纪元开始的计数几乎总是存在的(否则会很麻烦,而且几乎疯狂)。因此,您可能会混淆两个不同的方面:(a)从UTC(an)的历元开始计数,以及(b)同一时刻,但通过特定地区的人们使用的挂钟时间的镜头来看(a)

重要提示:作为一名程序员,学习在UTC中思考和工作。您的日志记录和存储/交换数据也都使用UTC将UTC视为唯一的真实时间™和所有其他都只是变体

另一个小贴士:不要把宝贵的时间和精力花在思考遗留的
日期
/
日历
课程上。随着业界领先的java.time类的出现,我们现在可以很高兴地抛弃它们

避免遗留日期时间类 您使用的是麻烦的旧日期时间类,现在已被java.time类取代。Android见下文

确保将历元数的计数处理为64位
long
/
long
而不是32位
int
/
整数

long input = 1_422_528_534_032L ; // Numeric literal for a `long` in modern Java.
该类表示时间线上的一个时刻,分辨率为(小数点的九(9)位)

instant.toString():2015-01-29T10:48:54.032Z

为了有效地将一天中的时间清除到00:00:00,我们可以通过指定来截断

InstantRuncated.toString():2015-01-29T00:00:00Z

如果要比较,可以从历元中提取计数

long millisSinceEpoch = instantTruncated.toEpochMilli() ;
142248960000

为了好玩,让我们计算一下增量

long delta = ( input - millisSinceEpoch ) ;
38934032

另外,让我们将该增量表示为一个函数,方法在该函数中生成标准格式的字符串

d、 toString():PT10H48M54.032S

看看这一切

如果你想看到同一时刻,时间轴上的点,通过特定地区的人们看到的挂钟时间镜头,应用时区()来获得一个对象

顺便说一句,虽然一天的开始在UTC中总是00:00:00,但在其他时区并不总是如此。由于夏令时(DST)和其他异常情况,某些区域中的某些日期可能在一天中的其他时间开始,例如01:00:00。让java.time确定一天的开始:

ZonedDateTime zdt = LocalDate.of( 2015 , Month.JANUARY , 29 ).atStartOfDay( ZoneId.of( "Asia/Gaza" ) ) ;
long millisFromEpoch = zdt.toInstant().toEpochMilli() ;  // Generate a count-from-epoch of UTC in milliseconds.

关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

从哪里获得java.time类

  • ,及以后
    • 内置的
    • 标准JavaAPI的一部分,带有捆绑实现
    • Java9添加了一些次要功能和修复
    • 大部分java.time功能都在中向后移植到Java6和Java7
    • 该项目专门为Android采用了ThreeTen Backport(如上所述)
tl;博士 2015-01-29T00:00:00Z

你的问题? 虽然不清楚,但我会将您的问题解释为:如何从历元数中进行计数,并将其更改为表示UTC中该日期的00:00:00时间

“如何以一致的毫秒值(long类型)的形式获取本地(设备上)时区中的当前日期?”

从大纪元开始的计数几乎总是存在的(否则会很麻烦,而且几乎疯狂)。因此,您可能会混淆两个不同的方面:(a)从UTC(an)的历元开始计数,以及(b)同一时刻,但通过特定地区的人们使用的挂钟时间的镜头来看(a)

重要提示:作为一名程序员,学习在UTC中思考和工作。所以t
long millisSinceEpoch = instantTruncated.toEpochMilli() ;
long delta = ( input - millisSinceEpoch ) ;
Duration d = Duration.ofMillis( delta ) ;
ZoneId z = ZoneId.of( "Europe/Sofia" ) ; // Or "Asia/Kolkata", whatever.
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment in history, but viewed using the wall-clock time in some particular region.
ZonedDateTime zdt = LocalDate.of( 2015 , Month.JANUARY , 29 ).atStartOfDay( ZoneId.of( "Asia/Gaza" ) ) ;
long millisFromEpoch = zdt.toInstant().toEpochMilli() ;  // Generate a count-from-epoch of UTC in milliseconds.