【问题标题】:Date to Day conversion in JavaJava中的日期到日期转换
【发布时间】:2011-10-31 11:25:21
【问题描述】:

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

 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 的 windows。

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

可能是什么问题?

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

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

【问题讨论】:

  • 您想获取自 1970 年 1 月 1 日以来的天数,忽略时区还是尊重时区?

标签: java date days


【解决方案1】:

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

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

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

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

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

但是,您应该明确指定要考虑哪个时区 - Date 代表时间即时,这意味着不同时区的不同日期。

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

【讨论】:

  • 我认为你回答错了问题。根据他的代码,他想获得自 1970 年 1 月 1 日以来的天数。
  • @AlexR:嗯,这部分取决于您在这里所说的日期是什么意思,以及 1970 年 1 月 1 日是什么意思。那是本地纪元还是 Unix 纪元?
  • 我必须计算自纪元以来的天数,输入将是 2011-03-18 - 自纪元为 15051 以来的天数 ..
  • @GKD:自 Unix 时代以来,即 UTC?如果是这样,为什么还要费心进行所有的转换呢?为什么不只使用你的最后一行,而是使用dateObj? (您的输入是 Date 对象,而不是字符串 - 重要区别。)
【解决方案2】:

java.time

java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用modern Date-Time API*

另外,下面引用的是来自home page of Joda-Time的通知:

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

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

您可以使用Date#toInstantjava.util.Date 的对象转换为Instant,然后您可以使用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 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2016-07-07
    • 2011-02-11
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    相关资源
    最近更新 更多