3

我可以使用以下代码将日期转换为天数。

 SimpleDateFormat sfd = new SimpleDateFormat("yyyy-MM-dd");
 String s1 = sfd.format(dateObj);
 String a1 [] = s1.split("-");
 int year = Integer.parseInt(a1[0].toString());
 int month = Integer.parseInt(a1[1])-1;
 int day = Integer.parseInt((a1[2]));

 Calendar c1 = Calendar.getInstance();
 c1.set(year,month,day);

 days = c1.getTime().getTime()/(24*60*60*1000);

上面的代码在我的系统中可以正常工作,该系统是时区 GMT +5.30 的窗口。

但是,当系统中的时间为 20.00 时,EST 或太平洋时区中的相同代码将最终结果加 1 天。

可能是什么问题 ?

我们是否需要在代码中明确设置时区?

输入日期不包含任何时间戳.. 存储java.util.Date而不是正确java.sql.Date吗?

4

2 回答 2

4

编辑:根据亚历克斯的评论,您的代码开头的问题可能使我对您的真正目标视而不见。

ADate代表时间的瞬间。根据时区的不同,这可能会落在不同的日期,但是您希望它如何影响事情呢?您想要自 Unix 纪元(始终为 UTC)以来的天数还是特定时区自 1970 年 1 月 1 日以来的天数?为什么你想要这个“天数”而不是日期的表示,例如LocalDate?这里的用例是什么?

编辑:如果您只想知道自 Unix 纪元以来的天数,您可以跳过大部分内容:

days = dateObj.getTime() / (24 * 60 * 60 * 1000);

您根本不应该仅仅为了获得年/月/日而进行格式化。只需创建一个Calendar,设置相关时区,setTime使用dateObj您已经获得的呼叫,然后清除日历的小时/分钟/秒部分。

但是,您应该明确指定要考虑的时区 - aDate表示时间的瞬间,这意味着不同时区的不同日期。

您还应该考虑使用Joda Time,它使这一切变得更简单,并且具有特定的日期类型 ( LocalDate)。这也可以很容易地找到 Unix 纪元和特定日期之间的天数,而无需自己执行除法。

于 2011-10-31T11:33:50.580 回答
0

java.time

java.util日期时间 API 及其格式化 API已SimpleDateFormat过时且容易出错。建议完全停止使用它们并切换到现代 Date-Time API *

另外,下面引用的是来自Joda-Time主页的通知:

请注意,从 Java SE 8 开始,用户被要求迁移到 java.time (JSR-310) - JDK 的核心部分,它取代了这个项目。

使用java.time现代日期时间 API 的解决方案:

您可以将对象转换java.util.DateInstantusing Date#toInstant,然后您可以使用 查找从现在到此日期的天数ChronoUnit#between

演示:

import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.GregorianCalendar;

public class Main {
    public static void main(String[] args) {
        // A sample java.util.Date
        Date dateObj = GregorianCalendar.from(ZonedDateTime.of(2021, 10, 2, 22, 25, 0, 0, ZoneOffset.UTC)).getTime();

        Instant instant = dateObj.toInstant();

        // Difference between now and the given java.util.Date
        System.out.println(ChronoUnit.DAYS.between(Instant.now(), instant));
    }
}

输出:

99

ONLINE DEMO

请注意,上面的代码计算以 UTC 表示的两个时刻/瞬间之间的天数。如果您有特定时区本地的日期时间值,则需要指定相应的ZoneId.

演示:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.GregorianCalendar;

public class Main {
    public static void main(String[] args) {
        ZoneId tz = ZoneId.of("Australia/Brisbane");

        // A sample java.util.Date representing the local date and time values in Australia/Brisbane
        Date dateObj = GregorianCalendar.from(ZonedDateTime.of(2021, 10, 2, 22, 25, 0, 0, tz)).getTime();

        // Difference between now in Australia/Brisbane and the given java.util.Date
        System.out.println(ChronoUnit.DAYS.between(Instant.now().atZone(tz), dateObj.toInstant().atZone(tz)));
    }
}

输出:

98

ONLINE DEMO

从Trail: Date Time了解有关现代日期时间 API 的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目和您的 Android API 工作level 仍然不符合 Java-8,请检查Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

于 2021-06-25T18:06:27.817 回答