Java 获取自日期对象起的天数,忽略时间

Java 获取自日期对象起的天数,忽略时间,java,android,date,Java,Android,Date,我不确定是否可以提高效率,但我需要获得自unix/epoch时间戳以来经过的天数,时间本身不是一个因素,只是与现在相比的日期 Example 1: Timestamp is : 3rd September 14:35 Compared to now which is: 4th September 00:35 Days difference = 1 Example 2: Timestamp is: 3rd September 23:55 Compared to now which is:

我不确定是否可以提高效率,但我需要获得自unix/epoch时间戳以来经过的天数,时间本身不是一个因素,只是与现在相比的日期

Example 1: 
Timestamp is : 3rd September 14:35 
Compared to now which is: 4th September 00:35 
Days difference = 1

Example 2:
Timestamp is: 3rd September 23:55
Compared to now which is: 4th September 00:35
Days difference = 1

Example 3:
Timestamp is: 2nd September 02:23
Compared to now which is: 4th September 00:35
Days difference = 2
要获取此信息,我有以下代码:

String epoch = "1599134401" // the unix/epoch timestamp in seconds
Long epochMillis = Long.valueOf(epoch) * 1000;
Date epochDateObj = new Date(epochMillis);
Calendar tsCal = Calendar.getInstance();
tsCal.setTime(epochDateObj);
tsCal.set(Calendar.HOUR_OF_DAY, 0);
tsCal.set(Calendar.MINUTE, 0);
tsCal.set(Calendar.SECOND, 0);
tsCal.set(Calendar.MILLISECOND, 0);

Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);

long diffInMillies = Math.abs(today.getTime().getTime() - tsCal.getTime().getTime());
long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
if(diff > 1) {
    return diff + " days";
} else {
    return diff + " day";
}
上面的代码可以工作,但对我来说,对于这样一个相当小的事情来说,它似乎相当复杂


有什么优化的建议吗?也许有一些功能我不知道。这是一款Android应用程序,它使用的是一个相当旧的SDK(回到Android 4.1)。

天基本上是人类的概念。它们涉及政治、观点、混乱、时区、时代、时代和其他非常复杂的概念。Date在地狱里没有snowball那样的机会去做正确的事情。日历也没有

你唯一的希望是一个合适的API,比如
java.time

此外,你需要澄清你的问题。你的要求是不可能的;你把枪比作祖母。大纪元时间从根本上说是一个“计算机”概念——它只指时间的某个时刻,它不知道你在问什么时候、在哪里、谁、哪个政党等等。这是一个问题,因为如果没有这些信息,就不可能知道今天是哪一天。秒或多或少是通用的,但天不是。一天可以是23小时或25小时,或23小时59分59秒,或24小时1秒,有时一整天都会被跳过,等等“一天有多长”是不可回答的,如果你不知道你问谁,以及什么时区(有时是政治实体!)被用作上下文

假设你在问亚利桑那州的某个人。答案在很大程度上取决于你在亚利桑那州询问的地点和询问的对象:你需要(潜在地)知道你碰巧询问的人是否在1970年以及“目标”时间使用夏令时。这取决于你是否在亚利桑那州境内的印第安人保留地询问,和/或你询问的人是否坚持NAR区。因此,为什么我提到了政治,为什么你想要的是完全不可能的

java.time
来拯救这场真正可以代表疯狂混乱的灾难

Instant
表示时间中的一个瞬间。它在内部存储为epoch millis,无法自己告诉您该时刻的日期、月、年、纪元、小时等。那是因为。。那是因为现实就是这样运作的。如果我现在咬断手指,问某人“现在几点了”,这取决于我在哪里,我问的人在哪里,他们归属于什么政党,所以这是不可能的。但是,你把一个
区域
和一个
即时
结合起来,现在我们就有进展了

LocalDateTime
表示一个人所说的时间:年/月/日+小时/分钟/秒。由于同样的原因,不可能反过来将其转换为埃波希米币。出于同样的原因,如果您将其与
区域相结合,门将开始打开

ZoneDateTime
试图弥合这一鸿沟:它代表了一个人所说的时间,但我们根据说它的人的位置(和政治派别)编码。您可以将其存储为LocalDateTime+时区或Instant+时区(当然,您不需要知道它是如何实现的)。当然,您可以从ZDT移动到Instant或LocalDateTime,这一个可以回答许多问题

让我们尝试解决您的问题:

String epoch = "1599134401"; // the unix/epoch timestamp in seconds
String where = "Europe/Berlin"; // what you want is impossible without this!!

Instant instant = Instant.ofEpochSecond(Long.valueOf(epoch));
ZonedDateTime target = instant.atZone(ZoneId.of(where));
ZonedDateTime today = ZonedDateTime.now(where);

long days = ChronoUnit.DAYS.between(target, today);
System.out.println(days);
一般来说,如果你在约会的时候开始认真计算,你会把事情搞砸,这是行不通的。当然,这并不是说你的测试永远都会抓住它;当时钟向后或向前移动,或者某个政党在夏时制结束前5天决定,或者客户端在一个地方,而服务器在另一个地方,等等,这些都是测试很少捕捉到的东西时,它会变得异常


正确使用java.time通常意味着你没有做太多的计算,幸运的是,它就在这里。

我强烈推荐rzwitserloot已经有了一个非常好的、有洞察力的答案。作为一个小的补充,我想让你看看我的代码。当然,仍然在使用java.time,这是现代的java日期和时间API

    ZoneId zone = ZoneId.of("Europe/Tirane");
    DateTimeFormatter epochSecondFormatter = new DateTimeFormatterBuilder()
            .appendValue(ChronoField.INSTANT_SECONDS)
            .toFormatter();
    
    String epoch = "1599134401"; // the unix/epoch timestamp in seconds
    Instant then = epochSecondFormatter.parse(epoch, Instant::from);
    LocalDate thatDay = then.atZone(zone).toLocalDate();
    
    LocalDate today = LocalDate.now(zone);
    
    long diff = ChronoUnit.DAYS.between(thatDay, today);
    diff = Math.abs(diff);
    if (diff == 1) {
        System.out.println("" + diff + " day");
    } else {
        System.out.println("" + diff + " days");
    }
刚才我运行代码时,输出是:

一天

由于要忽略一天中的时间,
LocalDate
是用于日期的正确类。
LocalDate
是一个带有时间的日期,没有时区

在英语中(虽然不是以英语为母语),我更喜欢说“0天”,而不是“0天”。所以我改变了你选择单数和复数的条件

您的代码工作正常吗?

你的代码在极端情况下给出了不准确的结果<代码>时间单位
通常是时间单位转换的良好枚举,但它假设一天总是24小时,正如rzwitserloot解释的那样,情况并非总是如此。该答案和本答案的java.time代码正确地考虑了夏季时间(DST)和其他时间异常之间的转换

问题:java.time在Android 4.1上工作吗? time在较旧和较新的Android设备上都能很好地工作。它至少需要Java6

  • 在Java8和更高版本以及更新的Android设备上(API级别26),现代API是内置的
  • 在非androidjava6和7中,获取三个后端口,即现代类的后端口(三个十用于jsr310;请参见底部的链接)
  • 在较旧的Android上,可以使用desugaring或Android版本的ThreeTen Backport。它叫ThreeTenABP。在后一种情况下,请确保使用子包从
    org.threeten.bp
    导入日期和时间类
链接
  • 解释如何使用java.time
  • ,其中
    java.time
    是第一个描述