Android / Java – date差异

我使用下面的代码获取当前date(格式为12/31/1999,即mm / dd / yyyy):

Textview txtViewData; txtViewDate.setText("Today is " + android.text.format.DateFormat.getDateFormat(this).format(new Date())); 

我还有一个格式为:2010-08-25(即yyyy / mm / dd),

所以我想find天数之间的差异,我怎么才能find在天差异?

(换句话说,我想findCURRENT DATE – yyyy / mm / dd格式化date之间的区别)

不是一个可靠的方法,更好的使用JodaTime

  Calendar thatDay = Calendar.getInstance(); thatDay.set(Calendar.DAY_OF_MONTH,25); thatDay.set(Calendar.MONTH,7); // 0-11 so 1 less thatDay.set(Calendar.YEAR, 1985); Calendar today = Calendar.getInstance(); long diff = today.getTimeInMillis() - thatDay.getTimeInMillis(); //result in millis 

这是一个近似…

 long days = diff / (24 * 60 * 60 * 1000); 

要parsingstring中的date,可以使用

  String strThatDay = "1985/08/25"; SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd"); Date d = null; try { d = formatter.parse(strThatDay);//catch exception } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } Calendar thatDay = Calendar.getInstance(); thatDay.setTime(d); //rest is the same.... 

虽然,因为您确定了date格式…您也可以对其子string进行Integer.parseInt()以获取其数值。

这不是我的工作,在这里find答案。 不想在未来的一个断开的链接:)。

关键是考虑日光设置的这条线,参考完整代码。

 TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); 

或者尝试将TimeZone作为parameter passing给daysBetween()并在sDateeDate对象中调用setTimeZone()

所以在这里:

 public static Calendar getDatePart(Date date){ Calendar cal = Calendar.getInstance(); // get calendar instance cal.setTime(date); cal.set(Calendar.HOUR_OF_DAY, 0); // set hour to midnight cal.set(Calendar.MINUTE, 0); // set minute in hour cal.set(Calendar.SECOND, 0); // set second in minute cal.set(Calendar.MILLISECOND, 0); // set millisecond in second return cal; // return the date part } 

getDatePart()取自这里

 /** * This method also assumes endDate >= startDate **/ public static long daysBetween(Date startDate, Date endDate) { Calendar sDate = getDatePart(startDate); Calendar eDate = getDatePart(endDate); long daysBetween = 0; while (sDate.before(eDate)) { sDate.add(Calendar.DAY_OF_MONTH, 1); daysBetween++; } return daysBetween; } 

细微差别find两个date之间的差异并不像减去两个date那样简单,而是将结果除以(24 * 60 * 60 * 1000)。 事实上,它的错误!

例如: 03/24/2007和03/25/2007的date应该是1天; 但是,使用上述方法,在英国,你会得到0天!

自己看(下面的代码)。 毫秒级的方式将导致错误的四舍五入,并且一旦你有了像“夏令时”这样的小东西,就会变得更加明显。

完整代码:

 import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; public class DateTest { public class DateTest { static SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy"); public static void main(String[] args) { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); //diff between these 2 dates should be 1 Date d1 = new Date("01/01/2007 12:00:00"); Date d2 = new Date("01/02/2007 12:00:00"); //diff between these 2 dates should be 1 Date d3 = new Date("03/24/2007 12:00:00"); Date d4 = new Date("03/25/2007 12:00:00"); Calendar cal1 = Calendar.getInstance();cal1.setTime(d1); Calendar cal2 = Calendar.getInstance();cal2.setTime(d2); Calendar cal3 = Calendar.getInstance();cal3.setTime(d3); Calendar cal4 = Calendar.getInstance();cal4.setTime(d4); printOutput("Manual ", d1, d2, calculateDays(d1, d2)); printOutput("Calendar ", d1, d2, daysBetween(cal1, cal2)); System.out.println("---"); printOutput("Manual ", d3, d4, calculateDays(d3, d4)); printOutput("Calendar ", d3, d4, daysBetween(cal3, cal4)); } private static void printOutput(String type, Date d1, Date d2, long result) { System.out.println(type+ "- Days between: " + sdf.format(d1) + " and " + sdf.format(d2) + " is: " + result); } /** Manual Method - YIELDS INCORRECT RESULTS - DO NOT USE**/ /* This method is used to find the no of days between the given dates */ public static long calculateDays(Date dateEarly, Date dateLater) { return (dateLater.getTime() - dateEarly.getTime()) / (24 * 60 * 60 * 1000); } /** Using Calendar - THE CORRECT WAY**/ public static long daysBetween(Date startDate, Date endDate) { ... } 

OUTPUT:

手册 – 2007年1月1日至2007年1月2日之间的天数为:1

日历 – 2007年1月1日至2007年1月2日之间的天数为:1


手动 – 2007年3月24日至2007年3月25日之间的天数为:0

日历 – 2007年3月24日至2007年3月25日之间的天数为:1

大多数的答案是好的,适合你的问题

所以我想find天数之间的差异,我如何find天差异?

我build议这个非常简单和直接的方法,保证在任何时区都能给你正确的区别:

 int difference= ((int)((startDate.getTime()/(24*60*60*1000)) -(int)(endDate.getTime()/(24*60*60*1000)))); 

而就是这样!

使用jodatime API

 Days.daysBetween(start.toDateMidnight() , end.toDateMidnight() ).getDays() 

“开始”和“结束”是你的DateTime对象。 parsingdatestring到DateTime对象使用parseDateTime方法

还有一个Android特定的JodaTime库 。

这个片段占夏时制,是O(1)。

 private final static long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000; private static long getDateToLong(Date date) { return Date.UTC(date.getYear(), date.getMonth(), date.getDate(), 0, 0, 0); } public static int getSignedDiffInDays(Date beginDate, Date endDate) { long beginMS = getDateToLong(beginDate); long endMS = getDateToLong(endDate); long diff = (endMS - beginMS) / (MILLISECS_PER_DAY); return (int)diff; } public static int getUnsignedDiffInDays(Date beginDate, Date endDate) { return Math.abs(getSignedDiffInDays(beginDate, endDate)); } 

这是简单和最好的计算,我可能会为你。

  try { /// String CurrDate= "10/6/2013"; /// String PrvvDate= "10/7/2013"; Date date1 = null; Date date2 = null; SimpleDateFormat df = new SimpleDateFormat("M/dd/yyyy"); date1 = df.parse(CurrDate); date2 = df.parse(PrvvDate); long diff = Math.abs(date1.getTime() - date2.getTime()); long diffDays = diff / (24 * 60 * 60 * 1000); System.out.println(diffDays); } catch (Exception e1) { System.out.println("exception " + e1); } 

Correct Way从山姆奎斯特的答案只有当第一个date早于第二个时才有效。 而且,如果两个date在一天之内,它将返回1。

这是最适合我的解决scheme。 就像大多数其他解决scheme一样,由于错误的日光节省偏移,它在一年中的两天仍然会显示不正确的结果。

 private final static long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000; long calculateDeltaInDays(Calendar a, Calendar b) { // Optional: avoid cloning objects if it is the same day if(a.get(Calendar.ERA) == b.get(Calendar.ERA) && a.get(Calendar.YEAR) == b.get(Calendar.YEAR) && a.get(Calendar.DAY_OF_YEAR) == b.get(Calendar.DAY_OF_YEAR)) { return 0; } Calendar a2 = (Calendar) a.clone(); Calendar b2 = (Calendar) b.clone(); a2.set(Calendar.HOUR_OF_DAY, 0); a2.set(Calendar.MINUTE, 0); a2.set(Calendar.SECOND, 0); a2.set(Calendar.MILLISECOND, 0); b2.set(Calendar.HOUR_OF_DAY, 0); b2.set(Calendar.MINUTE, 0); b2.set(Calendar.SECOND, 0); b2.set(Calendar.MILLISECOND, 0); long diff = a2.getTimeInMillis() - b2.getTimeInMillis(); long days = diff / MILLISECS_PER_DAY; return Math.abs(days); } 

最好和最简单的方法来做到这一点

  public int getDays(String begin) throws ParseException { long MILLIS_PER_DAY = 24 * 60 * 60 * 1000; SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH); long begin = dateFormat.parse(begin).getTime(); long end = new Date().getTime(); // 2nd date want to compare long diff = (end - begin) / (MILLIS_PER_DAY); return (int) diff; } 

使用以下function:

  /** * Returns the number of days between two dates. The time part of the * days is ignored in this calculation, so 2007-01-01 13:00 and 2007-01-02 05:00 * have one day inbetween. */ public static long daysBetween(Date firstDate, Date secondDate) { // We only use the date part of the given dates long firstSeconds = truncateToDate(firstDate).getTime()/1000; long secondSeconds = truncateToDate(secondDate).getTime()/1000; // Just taking the difference of the millis. // These will not be exactly multiples of 24*60*60, since there // might be daylight saving time somewhere inbetween. However, we can // say that by adding a half day and rounding down afterwards, we always // get the full days. long difference = secondSeconds-firstSeconds; // Adding half a day if( difference >= 0 ) { difference += SECONDS_PER_DAY/2; // plus half a day in seconds } else { difference -= SECONDS_PER_DAY/2; // minus half a day in seconds } // Rounding down to days difference /= SECONDS_PER_DAY; return difference; } /** * Truncates a date to the date part alone. */ @SuppressWarnings("deprecation") public static Date truncateToDate(Date d) { if( d instanceof java.sql.Date ) { return d; // java.sql.Date is already truncated to date. And raises an // Exception if we try to set hours, minutes or seconds. } d = (Date)d.clone(); d.setHours(0); d.setMinutes(0); d.setSeconds(0); d.setTime(((d.getTime()/1000)*1000)); return d; } 

所有这些解决scheme都有两个问题之一。 由于四舍五入错误,闰日和秒等原因,解决scheme不是完全准确的,或者您最终将循环使用两个未知date之间的天数。

这个解决scheme解决了第一个问题,并且将第二个问题提高了大约365倍,如果你知道你的最大范围是什么,那么这个问题会更好。

 /** * @param thisDate * @param thatDate * @param maxDays * set to -1 to not set a max * @returns number of days covered between thisDate and thatDate, inclusive, ie, counting both * thisDate and thatDate as an entire day. Will short out if the number of days exceeds * or meets maxDays */ public static int daysCoveredByDates(Date thisDate, Date thatDate, int maxDays) { //Check inputs if (thisDate == null || thatDate == null) { return -1; } //Set calendar objects Calendar startCal = Calendar.getInstance(); Calendar endCal = Calendar.getInstance(); if (thisDate.before(thatDate)) { startCal.setTime(thisDate); endCal.setTime(thatDate); } else { startCal.setTime(thatDate); endCal.setTime(thisDate); } //Get years and dates of our times. int startYear = startCal.get(Calendar.YEAR); int endYear = endCal.get(Calendar.YEAR); int startDay = startCal.get(Calendar.DAY_OF_YEAR); int endDay = endCal.get(Calendar.DAY_OF_YEAR); //Calculate the number of days between dates. Add up each year going by until we catch up to endDate. while (startYear < endYear && maxDays >= 0 && endDay - startDay + 1 < maxDays) { endDay += startCal.getActualMaximum(Calendar.DAY_OF_YEAR); //adds the number of days in the year startDate is currently in ++startYear; startCal.set(Calendar.YEAR, startYear); //reup the year } int days = endDay - startDay + 1; //Honor the maximum, if set if (maxDays >= 0) { days = Math.min(days, maxDays); } return days; } 

如果你需要date之间的date(不包括后者的date),只要摆脱+ 1当你看到endDay - startDay + 1

TL;博士

 ChronoUnit.DAYS.between( LocalDate.parse( "1999-12-28" ) , LocalDate.parse( "12/31/1999" , DateTimeFormatter.ofPattern( "MM/dd/yyyy" ) ) ) 

细节

其他答案已经过时。 与最早版本的Java捆绑在一起的旧date时间类已被certificate是devise不佳,混乱和麻烦的。 避免他们。

java.time

乔达时代项目取得了很大的成功,取代了那些老class级。 这些类为Java 8及更高版本中构build的java.time框架提供了灵感。

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

LocalDate

LocalDate类代表没有时间和没有时区的只有date的值。

分析string

如果你的inputstring是标准的ISO 8601格式, LocalDate类可以直接parsingstring。

 LocalDate start = LocalDate.parse( "1999-12-28" ); 

如果不是ISO 8601格式,则使用DateTimeFormatter定义格式模式。

 String input = "12/31/1999"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MM/dd/yyyy" ); LocalDate stop = LocalDate.parse( input , formatter ); 

通过ChronoUnit

现在获取这对LocalDate对象之间的天数。 ChronoUnit枚举计算已用时间。

 long totalDays = ChronoUnit.DAYS.between( start , stop ) ; 

如果您对Java枚举不熟悉,请了解它们在大多数其他编程语言中的传统枚举中function强大得多。 请参阅Enum类文档, Oracle教程和Wikipedia以了解更多信息。


关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧的遗留date时间类,如java.util.DateCalendarSimpleDateFormat

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

要了解更多信息,请参阅Oracle教程 。 并search堆栈溢出了很多例子和解释。 规范是JSR 310 。

从何处获取java.time类?

  • Java SE 8SE 9及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6SE 7
    • 大部分的java.timefunction都被移植到了ThreeTen-Backport中的 Java 6&7中。
  • Android的
    • ThreeTenABP项目专门针对Android,采用了ThreeTen-Backport (上文提到)。
    • 请参阅如何使用ThreeTenABP …。

ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。 你可能会在这里find一些有用的类,比如IntervalYearWeekYearQuarter 等等 。

有一个简单的解决scheme,至less对我来说是唯一可行的解​​决scheme。

问题是我看到的所有答案 – 使用乔达,日历,或date,或其他 – 只考虑毫秒的数量。 他们最终计算两个date之间的24小时周期 ,而不是实际的天数 。 所以从1月1日下午11点到1月2日凌晨1点,将会返回0天。

要计算startDateendDate之间的实际天数,只需执行以下操作:

 // Find the sequential day from a date, essentially resetting time to start of the day long startDay = startDate.getTime() / 1000 / 60 / 60 / 24; long endDay = endDate.getTime() / 1000 / 60 / 60 / 24; // Find the difference, duh long daysBetween = endDay - startDay; 

这将在1月2日到1月1日之间返回“1”。 如果您需要计算结束date,只需在daysBetween添加1(我需要在代码中执行此操作,因为我要计算范围内的总天数)。

这有点类似于丹尼尔所build议的,但是我认为更小的代码。

另一种方式是:

 public static int numberOfDaysBetweenDates(Calendar fromDay, Calendar toDay) { fromDay = calendarStartOfDay(fromDay); toDay = calendarStartOfDay(toDay); long from = fromDay.getTimeInMillis(); long to = toDay.getTimeInMillis(); return (int) TimeUnit.MILLISECONDS.toDays(to - from); } 

我发现了一个非常简单的方法来做到这一点,这就是我在我的应用程序中使用的。

假设你在Time对象中有date(或者其他什么,我们只需要毫秒):

 Time date1 = initializeDate1(); //get the date from somewhere Time date2 = initializeDate2(); //get the date from somewhere long millis1 = date1.toMillis(true); long millis2 = date2.toMillis(true); long difference = millis2 - millis1 ; //now get the days from the difference and that's it long days = TimeUnit.MILLISECONDS.toDays(difference); //now you can do something like if(days == 7) { //do whatever when there's a week of difference } if(days >= 30) { //do whatever when it's been a month or more } 

乔达时间

最好的方法是使用Joda-Time ,这是您将添加到项目中的非常成功的开源库。

 String date1 = "2015-11-11"; String date2 = "2013-11-11"; DateTimeFormatter formatter = new DateTimeFormat.forPattern("yyyy-MM-dd"); DateTime d1 = formatter.parseDateTime(date1); DateTime d2 = formatter.parseDateTime(date2); long diffInMillis = d2.getMillis() - d1.getMillis(); Duration duration = new Duration(d1, d2); int days = duration.getStandardDays(); int hours = duration.getStandardHours(); int minutes = duration.getStandardMinutes(); 

如果您使用的是Android Studio ,则非常容易添加joda时间。 在你的build.gradle(app)中:

 dependencies { compile 'joda-time:joda-time:2.4' compile 'joda-time:joda-time:2.4' compile 'joda-time:joda-time:2.2' } 
  Date userDob = new SimpleDateFormat("yyyy-MM-dd").parse(dob); Date today = new Date(); long diff = today.getTime() - userDob.getTime(); int numOfDays = (int) (diff / (1000 * 60 * 60 * 24)); int hours = (int) (diff / (1000 * 60 * 60)); int minutes = (int) (diff / (1000 * 60)); int seconds = (int) (diff / (1000));