与Java比较日期时的问题

ecfsfe2w  于 2023-03-28  发布在  Java
关注(0)|答案(5)|浏览(125)

现在,当我在Java中比较两个日期时,遇到了一些问题。
我想检查某个日期是否是下一周的同一天。
首先,我这样做:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());

        Calendar todayCalendar = Calendar.getInstance();
        Date today = sdf.parse(sdf.format(todayCalendar.getTime()));

        Step step = actualStep.getStep();
        Date plannedDate = sdf.parse(sdf.format(actualStep.getPlannedDate()));

        long diffInMillies = Math.abs(today.getTime() - plannedDate.getTime());
        long deltaDays = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS) +1L;

当我检查不同的值时,我得到这个:

Mon Mar 27 00:00:00 CEST 2023
Mon Mar 20 00:00:00 CET 2023
deltaDays: 7

所以我确实得到了7天的差异。问题是当我试图做一些单元测试时,我没有得到相同的结果:

Calendar todayCalendar = Calendar.getInstance();
        Date today = todayCalendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Integer day = 7;
        todayCalendar.add(Calendar.DAY_OF_WEEK, +day);
        Date expectedReminderDay = sdf.parse(sdf.format(todayCalendar.getTime()));

这一次,我得到:

Mon Mar 27 00:00:00 CEST 2023
Mon Apr 03 00:00:00 CEST 2023
deltaDays: 8

有谁知道为什么,在一种情况下,我得到8天的差异和7在另一个,而有一个星期分开?
感谢阅读!

dgjrabp2

dgjrabp21#

TL;医生

我想检查某个日期是否是下一周的同一天。

LocalDate            // Represent a date-only value. No time of day. No offset or time zone. 
.now()               // Capture the current date as seen in the JVM’s current default time zone. 
.getDayOfWeek()      // Get the `DayOfWeek` enum object for this date’s day of week: Monday though Sunday. 
.equals( 
    someOtherDate
    .getDayOfWeek()
)

详情

你使用的日期-时间类有很大的缺陷,它们已经过时了,几年前就被JSR 310中定义的现代 java.time 类所取代。
此外,您正在使用带时间的日期类来表示仅日期的值。因此,您选择的类型不合适。并且您的意外结果可能来自相关的时区问题,例如夏令时。
对于仅限日期的值,使用java.time.LocalDate。没有时间。没有UTC偏移量,也没有时区。没有夏令时。
要捕获当前日期,需要一个时区。对于任何给定的时刻,日期在地球仪各地因时区而异。
您可能希望使用JVM的当前时区,或者您可能希望查询用户。

ZoneId z = ZoneId.systemDefault() ;

获取当前日期。

LocalDate today = LocalDate.now( z ) ;

再加一周。

LocalDate nextWeek = today.plusWeeks( 1 ) ;

减去一周。

LocalDate weekAgo = today.minusWeeks( 1 ) ;

测试是否是一周中的同一天。您可以获取任何给定日期的DayOfWeek枚举对象。

boolean sameDayOfWeek = today.getDayOfWeek().equals( someOtherDate.getDayOfWeek() ) ;
zwghvu4y

zwghvu4y2#

+1L

long deltaDays = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS) +1L;

这使得7变成8。实际上,不是当前的阅读是你应该看的,而是你试图修复的先前读数:由于CET-CEST的变化,最初你有6天。由于时钟跳了一个小时,从3月20日00:00 CET到3月27日00:00 CEST之间有6天23小时,然后差值向下舍入,为6天。

gopyfrb3

gopyfrb33#

我认为你的问题是在“+天”行中:

todayCalendar.add(Calendar.DAY_OF_WEEK, +day);

试着把它改成“天”。我想“+”可能是在你把它加到当前天之前把你的天从7增加到8的“++”。
但是,请注意,类DateSimpleDateFormat已被弃用,并且强烈不建议使用,除非您使用遗留代码。请参阅自java 8以来可用的java.time包。您的相关类为DateTimeFormatterLocalDateDuration

w8biq8rn

w8biq8rn4#

不要使用字符串来比较数值。不要使用SimpleDateFormat。
日历本身可以做到这一点:

Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, 7);
int nextWeekYear = calendar.get(Calendar.YEAR);
int nextWeekMonth = calendar.get(Calendar.MONTH);
int nextWeekDay = calendar.get(Calendar.DATE);

calendar.Time(actualStep.getPlannedDate());
int plannedYear = calendar.get(Calendar.YEAR);
int plannedMonth = calendar.get(Calendar.MONTH);
int plannedDay = calendar.get(Calendar.DATE);

if (plannedYear == nextWeekYear &&
    plannedMonth == nextWeekMonth &&
    plannedDay == nextWeekDay) {

    // ....
}

正如其他人所指出的,你最好使用java.time.LocalDate而不是旧的Date类。Date是Java中C的time_t类型的等价物,它只是从1970年开始的毫秒计数。将它用于日历日期的问题是时区会使它变得非常复杂。例如,考虑以下代码:

Date date = new Date();
System.out.println(date.getTime());
System.out.println(date);

如果我晚上在电脑上运行它,我会看到:

1679972400000
Mon Mar 27 23:00:00 EDT 2023

但是如果我在英国运行相同的代码,我会看到:

1679972400000
Tue Mar 28 04:00:00 BST 2023

完全相同的Date值可以被解释为不同的日历日期,具体取决于它运行的位置。
但是如果你使用不受时区影响的LocalDate,所有这些问题都不再是问题:

public class Step {
    private LocalDate plannedDate = LocalDate.now();

    public LocalDate getPlannedDate() {
        return this.plannedDate;
    }
}

// ...

if (actualStep.getPlannedDate().equals(LocalDate.now().plusDays(7)) {
    // ...
}
7bsow1i6

7bsow1i65#

你在单元测试中增加了8天。day = 7,但是你增加了+day,这意味着day+1。从todayCalendar.add(Calendar.DAY_OF_WEEK, +day);中删除+,应该没问题。

相关问题