我一直在使用以下代码来计算两个日期之间的差异,我收到了一个不寻常的错误:
如果我通过以下日期:
d1 = 08/12/2017 d2 = 31/07/2022
它返回:24055 ..
是不是应该以月数返回的结果?
public static int CalcDateDiff( java.util.Date date1, java.util.Date date2) {
if(date1 == null || date2 ==null )
{
if(date2 == null)
{
Calendar d1 = Calendar.getInstance();
d1.setTime(date1);
final Calendar d2 = Calendar.getInstance();
int diff = (d2.get(Calendar.YEAR) - d1.get(Calendar.YEAR)) * 12 + d2.get(Calendar.MONTH) - d1.get(Calendar.MONTH);
return diff;
}
else
return -1;
}
else
{
Calendar d1 = Calendar.getInstance();
d1.setTime(date1);
final Calendar d2 = Calendar.getInstance();
d2.setTime(date2);
int diff = (d2.get(Calendar.YEAR) - d1.get(Calendar.YEAR)) * 12 + d2.get(Calendar.MONTH) - d1.get(Calendar.MONTH);
return diff;
}
}
提前致谢!
答案 0 :(得分:1)
如果您已经有java.sql.Date
个实例,那么
final Date d1 = new java.sql.Date(2017 - 1900, 12, 8);
final Date d2 = new java.sql.Date(2022 - 1900, 07, 31);
我知道我在
java.sql.Date
中使用了一个弃用的构造函数,这只是为了方便在最少的代码行中获得我需要的东西。 永远不要在生产代码中使用此构造函数!
最简单,最简单的自我记录方式来获得你想要的东西:
final long monthsBetween ChronoUnit.MONTHS.between(d1.toLocalDate(),d2.toLocalDate()) + 1;
因为使用这种方法,您不必使用TimeZone
信息,因为对于以这种方式创建的LocalDate
实例,所有信息都是正确的。
出于某种原因,只有java.sql.Date
只有.toLocalDate()
这对您有好处,因为这是您从数据库中获取的内容。
public LocalDate toLocalDate()
将此Date对象转换为 LocalDate转换创建一个表示相同的LocalDate 日期值作为本地时区的日期返回:表示相同日期值的LocalDate对象 以来: 1.8
(y2 - y1) * 12 + (m2 - m1) + 1
此外,您的代码过于复杂,使用的是非常旧的类。
public class Q47717075
{
/*
https://stackoverflow.com/questions/1086396/java-date-month-difference
*/
public static void main(@Nonnull final String[] args)
{
final Date d1 = new java.sql.Date(2017 - 1900, 12, 8);
final Date d2 = new java.sql.Date(2022 - 1900, 07, 31);
System.out.println(CalcDateDiff(d1, d2));
/* Obtains an instance of Instant from a text string such as 2007-12-03T10:15:30.00Z. */
System.out.println(intervalInMonths(LocalDate.of(2017,12,8), LocalDate.of(2022,7,31)));
System.out.println(ChronoUnit.MONTHS.between(d1.toLocalDate(),d2.toLocalDate()) + 1);
}
/*
Alternate Java 8 version
*/
public static int intervalInMonths(@Nonnull final LocalDate i1, @Nonnull final LocalDate i2)
{
final Period p = Period.between(i1, i2);
return (p.getYears() * 12) + p.getMonths() + 1;
}
/**
* Your versin corrected
*/
public static int CalcDateDiff(@Nonnull final Date date1, @Nonnull final Date date2)
{
final Calendar d1 = Calendar.getInstance();
d1.setTime(date1);
final Calendar d2 = Calendar.getInstance();
d2.setTime(date2);
return ((d2.get(YEAR) - d1.get(YEAR)) * 12 + (d2.get(MONTH) - d1.get(MONTH)) + 1);
}
}
56
56
56
答案 1 :(得分:0)
ChronoUnit.MONTHS.between( // Use enum method to calculate elapsed time.
date1.toInstant().atZone( ZoneId.of( "Africa/Casablanca " ) ) , // Convert from legacy `Date` class to modern `java.time.Instant` class. Adjust from UTC to a specific time zone.
date2.toInstant().atZone( ZoneId.of( "Africa/Casablanca " ) )
) // Return a number of months elapsed.
Answer by Roberson很好。这是另一种选择。
您对麻烦的Date
课程的使用现已过时。 java.time包中的Instant
替换了该遗留类。两者都代表片刻,UTC中时间轴上的一个点。现代课程的分辨率为nanoseconds而不是milliseconds。
使用添加到旧类的新方法进行转换。
Instant instant = myUtilDate.toInstant() ;
要确定几个月,我们需要日期。确定日期需要时区。对于任何特定时刻,日期在全球范围内因地区而异。
ZoneId z = ZoneId.of( "Pacific/Auckland " ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
ChronoUnit
枚举提供between
方法来计算已用时间。
long months = ChronoUnit.MONTHS.between( zdt1 , zdt2 ) ;