将1周添加到日期,首选哪种方式?

我正在审查工作中的一些代码,并发现代码处理如何处理当前时间1周的不一致,并想知道是否有任何理由为什么一个应该真正优先于另一个:

第一个是实用方法:

public static Date addDaysToDate(final Date date, int noOfDays) { Date newDate = new Date(date.getTime()); GregorianCalendar calendar = new GregorianCalendar(); calendar.setTime(newDate); calendar.add(Calendar.DATE, noOfDays); newDate.setTime(calendar.getTime().getTime()); return newDate; } 

第二个使用简单的毫秒算法:

 long theFuture = System.currentTimeMillis() + (86400 * 7 * 1000); Date nextWeek = new Date(theFuture); 

第二种方法显然使用“幻数”来定义一周,但是这可以移动到一个常量MILLISECONDS_IN_ONE_WEEK = 86400 * 7 * 1000除此之外,是否有任何理由为什么这些方法中的一种应该优先于另一种?

基本上我想改变代码在整个过程中保持一致,但我不完全确定删除哪一个。 所以任何论据都是有用的。

这两种方法在夏令时边界上的行为会有所不同。 无论夏令时状态如何,第一种方法将在一天中的同一时间继续返回。 第二种方法将返回在夏令时开始和停止时每个方向变化一小时的时间。

使用方法二要非常小心,这一天让我感到困惑。 考虑

 private static long ONE_YEAR_AS_MILLISECONDS = 365*24*60*60*1000; 

这看起来很无辜,但实际上不会产生预期的,因为乘法使用整数,当乘以每个其他整数时,会导致数字溢出并产生意外结果。 这是因为Java中的max int值是2,147,483,647,而一年中有31,536,000,000 ms。 在我的机器上,上面的代码产生1,471,228,928,这显然是不正确的。

相反,你需要这样做:

 private static long ONE_YEAR_AS_MILLISECONDS = 365L*24L*60L*60L*1000L; 

以下可以在java 8,Java 8摇滚中完成 !!

 public static void main(String[] args) { LocalDate today = LocalDate.now(); System.out.println("Current date: " + today); //add 1 week to the current date LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); System.out.println("Next week: " + nextWeek); } 

首先,我认为你用JodaTime取而代之。 http://joda-time.sourceforge.net/这是一个非常好的时间库。 您需要查看此页面,了解在特定时间点添加数天或数周是多么容易: http : //joda-time.sourceforge.net/key_period.html无法执行此操作,移动设备与不兼容的JVM。 游民。

您的第一个示例更易于阅读,开发人员将更容易使用。 它还使用Calendar类,这是在Java中操作日期的普遍接受的方式。 更好的是它有一个清晰的方法名称,可以设定它的function。

因此,如果您重构系统以始终使用com.DaveJ.util.date.DateUtils.addDaysToDate(最终日期日期,int noOfDays),那么您可以在该方法中执行任何操作,无论是Calendar还是millis或Joda,并且保持一致在您的申请中。 别忘了为它写一些unit testing!

越普遍,它就越有用。 如果你总是添加一周,我会选择第二种方法。 如果您有不同的添加,我会选择第一个,如果需要,可能会将天数替换为秒或甚至毫秒。

第一个会慢一点,所以如果性能问题,第二个更好。

这取决于! 由于闰秒,DST和其他日历怪异,这两者并不总是等价的。

对于商务和日常使用,总是使用第一种方法,性能也不差。 它会为你处理这些事情。

对于科学需求,通常你必须使用单调时钟(这里是第二个)。

当涉及夏令时的变化时,这两种方法可能会给出不同的结果。 想象一下当前时间是23:50而在02:00时钟跳到03:00。 当您只是以毫秒为单位添加7天时,第二天的时间为00:50。 增加7天,结果时间仍为23:50。

为了完成混淆,您还可以尝试add(Calendar.WEEK_OF_YEAR, 1) ,但不确定它会有多大差异。

由于您在移动设备上使用它,因此第一种方法更可取。 原因是您的代码应该独立于特定日历,DST和其他问题,例如秒超限(闰秒)。

您必须删除对GregorianCalendar依赖并使用Calendar.getInstance()创建它。

有关仅限日期的值,请参阅javaHelper的答案 。 LocalDate类故意没有时间和没有时区。

ZonedDateTime

对于日期时间值,使用ZonedDateTime表示日期和时间以及时区,以解决夏令时(DST)等exception。

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime now = ZonedDateTime.now( zoneId ); ZonedDateTime weekLater = now.plusWeeks( 1 ); 

或者添加一些任意天数。

 ZonedDateTime later = now.plusDays( someNumberOfDays ); 

关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了旧的麻烦的日期时间类,如java.util.Date.Calendarjava.text.SimpleDateFormat

现在处于维护模式的Joda-Time项目建议迁移到java.time。

要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。

大部分java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7,并进一步适应了ThreeTenABP中的 Android 。

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。