Java 中的日期到日转换

发布于 2024-12-12 17:23:07 字数 661 浏览 0 评论 0 原文

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

 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 中是否正确?

I am able to convert date to days using the below code.

 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);

The above code works accurately in my system which is windows with timezone GMT +5.30.

However the same code in EST or Pacific timezone adds a day by 1 to final result when the time is 20.00 in the system.

What could be the issue ?

Do we need to set Timezone explicitly in the code ?

input dates does not hold any time stamp ..
is it correct to store in java.util.Date instead of java.sql.Date?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

彼岸花ソ最美的依靠 2024-12-19 17:23:07

编辑:根据亚历克斯的评论,你的代码开头的问题可能让我看不到你的真正目标。

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

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

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

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

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

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

EDIT: As per Alex's comment, it's possible that the problems with the start of your code have blinded me to your real aim.

A Date represents an instant in time. That can fall on different dates depending on the time zone, but how do you want that to affect things? Do you want the number of days since the Unix epoch (which is always UTC) or the number of days since the 1st January 1970 in a particular time zone? Why do you want this "number of days" instead of a representation of a date such as LocalDate? What's the use case here?

EDIT: If you just want to know the number of days since the Unix epoch, you can skip most of this:

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

You shouldn't be going through formatting at all just to get the year / month / day. Just create a Calendar, set the relevant time zone, call setTime with the dateObj you've already got, and then clear the hour/minute/second part of the calendar.

However, you should explicitly specify which time zone you want to consider - a Date represents an instant in time, which will mean different dates in different time zones.

You should also consider using Joda Time which makes all of this simpler and has a specific type for dates (LocalDate). That would also make it easy to find the number of days between the Unix epoch and a particular date without performing the division yourself.

叫思念不要吵 2024-12-19 17:23:07

java.time

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

另外,下面引用的是Joda-Time主页的通知< /a>:

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

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

您可以将 java.util.Date 的对象转换为 即时使用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

在线演示< /a>

请注意,上面的代码计算以 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

在线演示< /a>

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


* 无论出于何种原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport 将大部分 java.time 功能向后移植到 Java 6 和 Java 6 7. 如果您正在处理 Android 项目,并且您的 Android API 级别仍然不符合 Java-8,请检查 通过脱糖提供 Java 8+ API如何在Android项目中使用ThreeTenABP

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Also, quoted below is a notice from the home page of Joda-Time:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

Solution using java.time, the modern Date-Time API:

You can convert the object of java.util.Date to Instant using Date#toInstant and then you can find the number of days from now until this date using ChronoUnit#between.

Demo:

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));
    }
}

Output:

99

ONLINE DEMO

Note that the above code calculates the number of days between two moments/instants represented in UTC. If you have date-time values local to a particular timezone, you need to specify the corresponding ZoneId.

Demo:

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)));
    }
}

Output:

98

ONLINE DEMO

Learn more about the modern Date-Time API from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文