如何从日期对象计算日期,如果我在周末,则在 java 中递增它?

问题描述 投票:0回答:1

我有 4 个日期,即今天(当前系统日期)、活动日期、quoteFinishFirstFolloupDate 和 quoteFinishSecondFollowupDate,我是根据某些标准计算出来的,但如果计算出的日期正好在周末(即周六、周日),那么我们需要增加或添加天数,以便下一个日期为工作日。那么,我如何计算天数并将其添加到工作日日期呢?我已经尝试了一些但是对于 Date 对象,我无法计算天数。

这是我的一段代码:

if (logs != null && logs.size() > 0) {
  ActivityLog latestActivityLog = logs.get(0);
  Date activityDate = latestActivityLog.getActivityDate();

  Date today = new Date();
  Calendar cal = Calendar.getInstance();
  cal.setTime(today);
  cal.set(Calendar.HOUR_OF_DAY, 0);
  cal.set(Calendar.MINUTE, 0);
  cal.set(Calendar.SECOND, 0);
  cal.set(Calendar.MILLISECOND, 0);

  int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
  // check if it is Saturday(day=7) or Sunday(day=1)
  if ((dayOfWeek == 7)) {
    cal.add(Calendar.DAY_OF_WEEK, 2);
    today = cal.getTime();
  }else if ((dayOfWeek == 1)) {
    cal.add(Calendar.DAY_OF_WEEK, 2);
    today = cal.getTime();
  }else {
    today = cal.getTime();
  }

  // @TODO: @RD to check +1 day logic
  // plus 1 to include the endate=today+26 with time at 1pm
  Date quoteFinishFirstFolloupDate = DateUtils.addDays(activityDate, -1 * getUnboundQuoteFirstFollowupDays());


  Date quoteFinishSecondFollowupDate = DateUtils.addDays(quoteFinishFirstFolloupDate, getUnboundQuoteSecondFollowupDays());

  if (today.compareTo(quoteFinishFirstFolloupDate) == 0 || today.compareTo(quoteFinishSecondFollowupDate) == 0) {
    isValidCCVB_ActivityLog = Boolean.TRUE;
    log.info("isValidCCVB_ActivityLog:" + isValidCCVB_ActivityLog);
  }
}

有人能帮帮我吗?

java datetime calendar
1个回答
0
投票

tl;博士

Calendar c =
    GregorianCalendar.from(                                            // A subclass of `Calendar` legacy class.
        myLegacyJavaUtilDate                                           // Legacy class representing a moment as seen in UTC.  
        .toInstant()                                                   // Convert this moment as seen in UTC from legacy class to modern class.
        .atZone( ZoneId.of( "Asia/Tokyo" ) )                           // See the same moment through the wall-clock date & time of a particular time zone. Returns an `ZonedDateTime`. 
        .toLocalDate()                                                 // Extract a date-only value.
        .with( org.threeten.extra.Temporals.nextWorkingDayOrSame()     // Move to the next weekday if not already a weekday.
        .atStartOfDay( ZoneId.of( "Asia/Tokyo" ) )                     // Determine the first moment of the day as seen in that zone on that date. Returns an `ZonedDateTime`. 
    )
;

避免遗留日期时间类

避免有问题的遗留日期时间类,例如

Date
类。如果需要与尚未更新到 java.time 类的旧代码进行互操作,请在 java.time 中编写新逻辑,最后转换为遗留对象。

java.time.Instant
是新的
java.util.Date
.

java.util.Date
类被
java.time.Instant
取代。使用添加到旧类的新方法进行转换。

Instant instant = myJUDate.toInstant() ;

仅限日期值:
LocalDate

你说:

  Date today = new Date();
  Calendar cal = Calendar.getInstance();
  cal.setTime(today);
  cal.set(Calendar.HOUR_OF_DAY, 0);
  cal.set(Calendar.MINUTE, 0);
  cal.set(Calendar.SECOND, 0);
  cal.set(Calendar.MILLISECOND, 0);

显然,您想从

java.util.Date
对象中提取仅日期值,该对象包含日期和时间,与 UTC 的偏移量为零小时-分钟-秒。要正确提取日期,您必须指定要解释日期的时区。对于任何给定时刻,世界各地的日期因时区而异。

Instant instant = myJUDate.toInstant() ;    // A moment as seen in UTC.
ZoneId z = ZoneId.of( "Asia/Tokyo" ); 
ZonedDateTime zdt = instant.atZone( z ) ;   // The same simultaneous moment, but as seen through a particular time zone. The time of day, and even the date, may differ from that of the `Instant` above.
LocalDate localDate = zdt.toLocalDate() ;   // Extract a date only, discarding the time-of-day and the time zone.

或更简单地说:

LocalDate localDate =
    myJUDate
    .toInstant()
    .atZone( ZoneId.of( "Asia/Tokyo" ) )
    .toLocalDate()
;

对 4 个

java.util.Date
输入中的 3 个使用这种代码。对于当前日期,今天,使用这个:

LocalDate today = LocalDate.now( z ) ;

在日期之间移动

你问:

如果计算出的日期正好是周末(即周六、周日),那么我们需要增加或增加天数,以便下一个日期为工作日。

这在 java.time.

中非常简单

TemporalAdjuster
界面提供从一个日期移动到另一个日期。您希望在日期之间跳转的算法在该接口的实现中定义。

TemporalAdjusters
类提供了几个有用的此类实现。但是这些捆绑的实现都不会在周六和周日跳转。

第三方库ThreeTen-Extra恰好提供了

TemporalAdjuster
的实现,它做的正是你想要的,跳过周六和周日。将该库添加到您的项目中。然后访问调用
TemporalAdjuster
 返回的 
org.threeten.extra.Temporals.nextWorkingDayOrSame()
对象。 “OrSame”表示如果日期已经是工作日,则保留它,无需移动到另一个日期。

TemporalAdjuster nextOrSameWeekdayAdjuster = org.threeten.extra.Temporals.nextWorkingDayOrSame() ;

让调节器在您关心的每个日期工作。

LocalDate nextOrSameWeekDayClosestToToday = today.with( nextOrSameWeekdayAdjuster ) ;

注意java.time 使用不可变对象。不是改变(“变异”)原始对象,而是返回一个新对象,其值基于原始对象。

从仅限日期的值中获取时刻

所以我们调整了一些

LocalDate
对象来避开周末。但是你要求
java.util.Date
对象(显然)。

要从仅限日期的值 (

LocalDate
) 到某个时刻,我们必须应用一个时区来确定该地区当天的第一时刻。

不要假设一天从 00:00 开始。某些时区的某些日期从另一个时间开始,例如 01:00。让java.time确定第一个时刻。

ZonedDateTime firstMomentOfNextOrSameWeekDayClosestToToday = nextOrSameWeekDayClosestToToday.atStartOfDay( z ) ;

从现代类转换为传统类

您评论:

但是由于一些限制,我使用的是日期和日历类。

如上所述,您应该避免使用遗留的日期时间类。他们真的有那么麻烦。

但是,如果您必须让遗留类的对象与尚未更新到 java.time 的旧代码进行互操作,请调用添加到旧类的新转换方法。

要转换,首先从我们的

java.time.Instant
对象中提取一个
java.time.ZonedDateTime

Instant instant = firstMomentOfNextOrSameWeekDayClosestToToday.toInstant() ;

然后从现代转换为传统。

java.util.Date d = java.util.Date.from( instant ) ;

如果您想要在我们特定时区看到的时刻而不是 UTC (

java.util.Date
) 中看到的时刻,请将
ZonedDateTime
转换为从
GregorianCalendar
延伸的
Calendar
类。

Calendar c = GregorianCalendar.from( firstMomentOfNextOrSameWeekDayClosestToToday ) ;

将所有这些代码放在一起:

Calendar c =
    GregorianCalendar.from( 
        myJUDate
        .toInstant()
        .atZone( ZoneId.of( "Asia/Tokyo" ) )
        .toLocalDate()
        .with( org.threeten.extra.Temporals.nextWorkingDayOrSame() ) 
        .atStartOfDay( ZoneId.of( "Asia/Tokyo" ) ) 
    )
;
© www.soinside.com 2019 - 2024. All rights reserved.