我需要找到两个日期之间的天数:一个来自报告,一个是当前日期。我的片段:
int age=calculateDifference(agingDate, today);
此处calculateDifference
是一种私有方法,agingDate
和today
是Date
个对象,仅供您澄清。我已经关注了Java论坛的两篇文章,Thread 1 / Thread 2。
它在独立程序中运行良好,但是当我将其包含在我的逻辑中以从报告中读取时,我会得到一个不寻常的值差异。
为什么会发生这种情况?我该如何解决?
编辑:
与实际天数相比,我获得的天数更多。
public static int calculateDifference(Date a, Date b)
{
int tempDifference = 0;
int difference = 0;
Calendar earlier = Calendar.getInstance();
Calendar later = Calendar.getInstance();
if (a.compareTo(b) < 0)
{
earlier.setTime(a);
later.setTime(b);
}
else
{
earlier.setTime(b);
later.setTime(a);
}
while (earlier.get(Calendar.YEAR) != later.get(Calendar.YEAR))
{
tempDifference = 365 * (later.get(Calendar.YEAR) - earlier.get(Calendar.YEAR));
difference += tempDifference;
earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
}
if (earlier.get(Calendar.DAY_OF_YEAR) != later.get(Calendar.DAY_OF_YEAR))
{
tempDifference = later.get(Calendar.DAY_OF_YEAR) - earlier.get(Calendar.DAY_OF_YEAR);
difference += tempDifference;
earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
}
return difference;
}
注意:
不幸的是,没有一个答案帮助我解决了这个问题。我已经在this problem库的帮助下完成了Joda-time。
答案 0 :(得分:148)
我建议您使用优秀的Joda Time库而不是有缺陷的java.util.Date和朋友。你可以简单地写一下
import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.Days;
Date past = new Date(110, 5, 20); // June 20th, 2010
Date today = new Date(110, 6, 24); // July 24th
int days = Days.daysBetween(new DateTime(past), new DateTime(today)).getDays(); // => 34
答案 1 :(得分:48)
我可能来不及加入游戏,但是到底是什么? :)
您认为这是一个线程问题吗?例如,您如何使用此方法的输出? OR
我们是否可以将代码更改为执行以下操作:
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.set(<your earlier date>);
calendar2.set(<your current date>);
long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
long diffSeconds = diff / 1000;
long diffMinutes = diff / (60 * 1000);
long diffHours = diff / (60 * 60 * 1000);
long diffDays = diff / (24 * 60 * 60 * 1000);
System.out.println("\nThe Date Different Example");
System.out.println("Time in milliseconds: " + diff
+ " milliseconds.");
System.out.println("Time in seconds: " + diffSeconds
+ " seconds.");
System.out.println("Time in minutes: " + diffMinutes
+ " minutes.");
System.out.println("Time in hours: " + diffHours
+ " hours.");
System.out.println("Time in days: " + diffDays
+ " days.");
}
答案 2 :(得分:23)
diff /(24 * etc)不考虑Timezone,所以如果您的默认时区中有DST,它可以关闭计算。
这个link有一个很好的实现。
以下是链接断开时上述链接的来源:
/** Using Calendar - THE CORRECT WAY**/
public static long daysBetween(Calendar startDate, Calendar endDate) {
//assert: startDate must be before endDate
Calendar date = (Calendar) startDate.clone();
long daysBetween = 0;
while (date.before(endDate)) {
date.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
return daysBetween;
}
和
/** Using Calendar - THE CORRECT (& Faster) WAY**/
public static long daysBetween(final Calendar startDate, final Calendar endDate)
{
//assert: startDate must be before endDate
int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
long endInstant = endDate.getTimeInMillis();
int presumedDays =
(int) ((endInstant - startDate.getTimeInMillis()) / MILLIS_IN_DAY);
Calendar cursor = (Calendar) startDate.clone();
cursor.add(Calendar.DAY_OF_YEAR, presumedDays);
long instant = cursor.getTimeInMillis();
if (instant == endInstant)
return presumedDays;
final int step = instant < endInstant ? 1 : -1;
do {
cursor.add(Calendar.DAY_OF_MONTH, step);
presumedDays += step;
} while (cursor.getTimeInMillis() != endInstant);
return presumedDays;
}
答案 3 :(得分:16)
在Java 8及更高版本中,使用java.time framework(Tutorial)。
Duration
Duration
类表示一个时间跨度,以秒为单位加上小数秒。它可以计算天,小时,分钟和秒。
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println(duration.toDays());
ChronoUnit
如果您只需要天数,或者您可以使用ChronoUnit
enum。请注意,计算方法返回long
而不是int
。
long days = ChronoUnit.DAYS.between( then, now );
答案 4 :(得分:13)
这取决于你定义的差异。要比较午夜的两个日期,你可以这样做。
long day1 = ...; // in milliseconds.
long day2 = ...; // in milliseconds.
long days = (day2 - day1) / 86400000;
答案 5 :(得分:13)
import java.util.Calendar;
import java.util.Date;
public class Main {
public static long calculateDays(String startDate, String endDate)
{
Date sDate = new Date(startDate);
Date eDate = new Date(endDate);
Calendar cal3 = Calendar.getInstance();
cal3.setTime(sDate);
Calendar cal4 = Calendar.getInstance();
cal4.setTime(eDate);
return daysBetween(cal3, cal4);
}
public static void main(String[] args) {
System.out.println(calculateDays("2012/03/31", "2012/06/17"));
}
/** Using Calendar - THE CORRECT WAY**/
public static long daysBetween(Calendar startDate, Calendar endDate) {
Calendar date = (Calendar) startDate.clone();
long daysBetween = 0;
while (date.before(endDate)) {
date.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
return daysBetween;
}
}
答案 6 :(得分:9)
解决方案使用毫秒时间之间的差异,并正确舍入DST日期:
public static long daysDiff(Date from, Date to) {
return daysDiff(from.getTime(), to.getTime());
}
public static long daysDiff(long from, long to) {
return Math.round( (to - from) / 86400000D ); // 1000 * 60 * 60 * 24
}
一个注意事项:当然,日期必须在某个时区。
重要代码:
Math.round( (to - from) / 86400000D )
如果您不想要回合,可以使用UTC日期,
答案 7 :(得分:4)
问题的说明:(我的代码是在几周内计算delta,但同样的问题适用于delta天数)
这是一个非常合理的实现:
public static final long MILLIS_PER_WEEK = 7L * 24L * 60L * 60L * 1000L;
static public int getDeltaInWeeks(Date latterDate, Date earlierDate) {
long deltaInMillis = latterDate.getTime() - earlierDate.getTime();
int deltaInWeeks = (int)(deltaInMillis / MILLIS_PER_WEEK);
return deltaInWeeks;
}
但是这个测试会失败:
public void testGetDeltaInWeeks() {
delta = AggregatedData.getDeltaInWeeks(dateMar09, dateFeb23);
assertEquals("weeks between Feb23 and Mar09", 2, delta);
}
原因是:
Mon Mar 09 00:00:00 EDT 2009 = 1,236,571,200,000
星期一2月23日 00:00:00 EST 2009 = 1,235,365,200,000
MillisPerWeek = 604,800,000
因此,(Mar09 - Feb23)/ MillisPerWeek =
1,206,000,000 / 604,800,000 = 1.994 ......
但是看日历的任何人都同意答案是2。
答案 8 :(得分:3)
我使用这个功能:
DATEDIFF("31/01/2016", "01/03/2016") // me return 30 days
我的职能:
import java.util.Date;
public long DATEDIFF(String date1, String date2) {
long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000;
long days = 0l;
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); // "dd/MM/yyyy HH:mm:ss");
Date dateIni = null;
Date dateFin = null;
try {
dateIni = (Date) format.parse(date1);
dateFin = (Date) format.parse(date2);
days = (dateFin.getTime() - dateIni.getTime())/MILLISECS_PER_DAY;
} catch (Exception e) { e.printStackTrace(); }
return days;
}
答案 9 :(得分:2)
查看此apache commons-lang类DateUtils
中的 getFragmentInDays 方法。
答案 10 :(得分:2)
根据@ Mad_Troll的回答,我开发了这种方法。
我针对它运行了大约30个测试用例,是唯一能正确处理子日时间片段的方法。
示例:如果你现在通过&amp;现在+ 1毫秒仍然是同一天。
执行1-1-13 23:59:59.098
到1-1-13 23:59:59.099
会正确返回0天;分配到此处发布的其他方法将无法正确执行此操作。
值得注意的是,它并不关心你把它们放进去的方式,如果你的结束日期早于开始日期,那么它将倒数。
/**
* This is not quick but if only doing a few days backwards/forwards then it is very accurate.
*
* @param startDate from
* @param endDate to
* @return day count between the two dates, this can be negative if startDate is after endDate
*/
public static long daysBetween(@NotNull final Calendar startDate, @NotNull final Calendar endDate) {
//Forwards or backwards?
final boolean forward = startDate.before(endDate);
// Which direction are we going
final int multiplier = forward ? 1 : -1;
// The date we are going to move.
final Calendar date = (Calendar) startDate.clone();
// Result
long daysBetween = 0;
// Start at millis (then bump up until we go back a day)
int fieldAccuracy = 4;
int field;
int dayBefore, dayAfter;
while (forward && date.before(endDate) || !forward && endDate.before(date)) {
// We start moving slowly if no change then we decrease accuracy.
switch (fieldAccuracy) {
case 4:
field = Calendar.MILLISECOND;
break;
case 3:
field = Calendar.SECOND;
break;
case 2:
field = Calendar.MINUTE;
break;
case 1:
field = Calendar.HOUR_OF_DAY;
break;
default:
case 0:
field = Calendar.DAY_OF_MONTH;
break;
}
// Get the day before we move the time, Change, then get the day after.
dayBefore = date.get(Calendar.DAY_OF_MONTH);
date.add(field, multiplier);
dayAfter = date.get(Calendar.DAY_OF_MONTH);
// This shifts lining up the dates, one field at a time.
if (dayBefore == dayAfter && date.get(field) == endDate.get(field))
fieldAccuracy--;
// If day has changed after moving at any accuracy level we bump the day counter.
if (dayBefore != dayAfter) {
daysBetween += multiplier;
}
}
return daysBetween;
}
您可以删除@NotNull
注释,这些注释由Intellij用于动态执行代码分析
答案 11 :(得分:1)
你说它“在独立程序中运行良好”,但是当你“将其包含在我的逻辑中以便从报告中读取”时,你会得到“不寻常的差异值”。这表明您的报告具有一些无法正常工作的值,并且您的独立程序没有这些值。我推荐一个测试用例,而不是一个独立的程序。编写一个测试用例就像一个独立程序一样,从JUnit的TestCase类继承。现在,您可以运行一个非常具体的示例,知道您期望的值(并且今天不要为测试值提供它,因为今天随着时间的推移而变化)。如果您输入在独立程序中使用的值,您的测试可能会通过。那很好 - 你希望这些案例继续有效。现在,从报表中添加一个值不正常的值。您的新测试可能会失败。弄清楚它为什么失败,修复它并变为绿色(所有测试都通过)。运行您的报告。看看还在打破什么;写一个测试;让它通过。很快你就会发现你的报告正在发挥作用。
答案 12 :(得分:1)
这个基本功能的数百行代码???
只是一个简单的方法:
protected static int calculateDayDifference(Date dateAfter, Date dateBefore){
return (int)(dateAfter.getTime()-dateBefore.getTime())/(1000 * 60 * 60 * 24);
// MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
}
答案 13 :(得分:1)
Answer by Vitalii Fedorenko是正确的,描述了如何使用内置于Java 8及更高版本的java.time类(Duration
&amp; ChronoUnit
)以现代方式执行此计算(和back-ported to Java 6 & 7和to Android)。
Days
如果您在代码中经常使用了几天,则可以使用类替换纯粹的整数。 Days
类可以在ThreeTen-Extra项目中找到,它是java.time的扩展,并为将来可能添加到java.time提供了基础。 Days
类提供了一种类型安全的方式来表示应用程序中的天数。该类包括ZERO
和ONE
的便捷常量。
鉴于问题中过时的java.util.Date
对象,请先将它们转换为现代java.time.Instant
个对象。旧的日期时间类具有新添加的方法,以便于转换为java.time,例如java.util.Date::toInstant
。
Instant start = utilDateStart.toInstant(); // Inclusive.
Instant stop = utilDateStop.toInstant(); // Exclusive.
将Instant
个对象传递给org.threeten.extra.Days
的工厂方法。
在当前的实现(2016-06)中,这是一个调用java.time.temporal.ChronoUnit.DAYS.between
的包装器,请阅读ChronoUnit
类doc以获取详细信息。需要说明的是:所有大写DAYS
都在枚举ChronoUnit
中,而initial-cap Days
是来自ThreeTen-Extra的类。
Days days = Days.between( start , stop );
您可以围绕自己的代码传递这些Days
个对象。您可以通过调用toString
以标准ISO 8601格式序列化为字符串。这种PnD
格式使用P
标记开头,D
表示“天”,中间有几天。在生成和解析表示日期时间值的字符串时,默认情况下java.time类和ThreeTen-Extra都使用这些标准格式。
String output = days.toString();
P3D
Days days = Days.parse( "P3D" );
答案 14 :(得分:1)
public static int getDifferenceIndays(long timestamp1, long timestamp2) {
final int SECONDS = 60;
final int MINUTES = 60;
final int HOURS = 24;
final int MILLIES = 1000;
long temp;
if (timestamp1 < timestamp2) {
temp = timestamp1;
timestamp1 = timestamp2;
timestamp2 = temp;
}
Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
endDate.setTimeInMillis(timestamp1);
startDate.setTimeInMillis(timestamp2);
if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
int day1 = endDate.get(Calendar.DAY_OF_MONTH);
int day2 = startDate.get(Calendar.DAY_OF_MONTH);
if (day1 == day2) {
return 0;
} else {
return 1;
}
}
int diffDays = 0;
startDate.add(Calendar.DAY_OF_MONTH, diffDays);
while (startDate.before(endDate)) {
startDate.add(Calendar.DAY_OF_MONTH, 1);
diffDays++;
}
return diffDays;
}
答案 15 :(得分:0)
您应该使用Joda Time库,因为Java Util Date有时会返回错误的值。
Joda vs Java Util Date
例如昨天(dd-mm-yyyy,12-07-2016)和1957年的第一天(dd-mm-yyyy,01-01-1957)之间的日子:
public class Main {
public static void main(String[] args) {
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
Date date = null;
try {
date = format.parse("12-07-2016");
} catch (ParseException e) {
e.printStackTrace();
}
//Try with Joda - prints 21742
System.out.println("This is correct: " + getDaysBetweenDatesWithJodaFromYear1957(date));
//Try with Java util - prints 21741
System.out.println("This is not correct: " + getDaysBetweenDatesWithJavaUtilFromYear1957(date));
}
private static int getDaysBetweenDatesWithJodaFromYear1957(Date date) {
DateTime jodaDateTime = new DateTime(date);
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy");
DateTime y1957 = formatter.parseDateTime("01-01-1957");
return Days.daysBetween(y1957 , jodaDateTime).getDays();
}
private static long getDaysBetweenDatesWithJavaUtilFromYear1957(Date date) {
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
Date y1957 = null;
try {
y1957 = format.parse("01-01-1957");
} catch (ParseException e) {
e.printStackTrace();
}
return TimeUnit.DAYS.convert(date.getTime() - y1957.getTime(), TimeUnit.MILLISECONDS);
}
所以我真的建议你使用Joda Time库。
答案 16 :(得分:0)
我已经写过这篇文章了。这是Calculating the difference between two Java date instances的重新发布。
public int getDiffernceInDays(long timeAfter, long timeBefore) {
Calendar calendarAfter = Calendar.getInstance();
calendarAfter.setTime(new Date(timeAfter));
Calendar calendarNewAfter = Calendar.getInstance();
calendarNewAfter.set(calendarAfter.get(Calendar.YEAR), calendarAfter.get(Calendar.MONTH), calendarAfter.get(Calendar.DAY_OF_MONTH));
Calendar calendarBefore = Calendar.getInstance();
calendarBefore.setTime(new Date(timeBefore));
Calendar calendarNewBefore = Calendar.getInstance();
calendarNewBefore.set(calendarBefore.get(Calendar.YEAR), calendarBefore.get(Calendar.MONTH), calendarBefore.get(Calendar.DAY_OF_MONTH));
return (int) ((calendarNewAfter.getTime().getTime() - calendarNewBefore.getTime().getTime()) / (24 * 60 * 60 * 1000));
}
答案 17 :(得分:0)
如果您正在寻找能够在两者之间返回正确数量或天数的解决方案,例如11/30/2014 23:59
和12/01/2014 00:01
这里使用Joda Time的解决方案。
private int getDayDifference(long past, long current) {
DateTime currentDate = new DateTime(current);
DateTime pastDate = new DateTime(past);
return currentDate.getDayOfYear() - pastDate.getDayOfYear();
}
此实现将返回1
作为天数的差异。此处发布的大多数解决方案计算两个日期之间的毫秒差异。这意味着将返回0
,因为这两个日期之间只有2分钟的差异。
答案 18 :(得分:0)
此代码计算2个日期字符串之间的天数:
static final long MILLI_SECONDS_IN_A_DAY = 1000 * 60 * 60 * 24;
static final String DATE_FORMAT = "dd-MM-yyyy";
public long daysBetween(String fromDateStr, String toDateStr) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
Date fromDate;
Date toDate;
fromDate = format.parse(fromDateStr);
toDate = format.parse(toDateStr);
return (toDate.getTime() - fromDate.getTime()) / MILLI_SECONDS_IN_A_DAY;
}
答案 19 :(得分:-6)
Date d1 = jDateChooserFrom.getDate();
Date d2 = jDateChooserTo.getDate();
Calendar day1 = Calendar.getInstance();
day1.setTime(d1);
Calendar day2 = Calendar.getInstance();
day2.setTime(d2);
int from = day1.get(Calendar.DAY_OF_YEAR);
int to = day2.get(Calendar.DAY_OF_YEAR);
int difference = to-from;