Otrzymuję aktualną datę (w formacie 12/31/1999 tj. Mm / dd / rrrr) zgodnie z poniższym kodem:
Textview txtViewData;
txtViewDate.setText("Today is " +
android.text.format.DateFormat.getDateFormat(this).format(new Date()));
i mam inną datę w formacie: 2010-08-25 (tj. rrrr / mm / dd),
więc chcę znaleźć różnicę między datą w liczbie dni, jak znaleźć różnicę w dniach?
(Innymi słowy, chcę znaleźć różnicę między datą bieżącą a datą w formacie rrrr / mm / dd )
Odpowiedzi:
Niezbyt niezawodna metoda, lepsza od 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
Oto przybliżenie ...
long days = diff / (24 * 60 * 60 * 1000);
Aby przeanalizować datę z ciągu, możesz użyć
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....
Chociaż, ponieważ jesteś pewien formatu daty ... Możesz również zrobić
Integer.parseInt()
na jego Podłańcuchach, aby uzyskać ich wartości liczbowe.źródło
("yyyy/mm/dd");
powinno być zastąpione przez Wielkie("yyyy/MM/dd");
M na miesiąc, małe litery na minuty. Poprawione.Math.round(millisBetweenDates * 1f / TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS));
To NIE jest moja praca, znalazłem odpowiedź tutaj . nie chciał zepsutego linku w przyszłości :).
Kluczem jest ten wiersz do uwzględnienia ustawienia światła dziennego, zob. Pełny kod.
TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
lub spróbuj przechodząc
TimeZone
jako parametrdaysBetween()
i wywołaniesetTimeZone()
wsDate
ieDate
obiektów.Więc oto idzie:
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 () pobrane stąd
/** * 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; }
Niuanse: Znalezienie różnicy między dwiema datami nie jest tak proste, jak odjęcie dwóch dat i podzielenie wyniku przez (24 * 60 * 60 * 1000). W rzeczywistości jego błędne!
Na przykład: Różnica między dwiema datami 24.03.2007 i 25.03.2007 powinna wynosić 1 dzień; Jednak korzystając z powyższej metody, w Wielkiej Brytanii otrzymasz 0 dni!
Przekonaj się sam (kod poniżej). Podążanie drogą milisekund doprowadzi do zaokrąglenia błędów i staną się one najbardziej widoczne, gdy pojawi się taka drobnostka jak czas letni.
Pełny kod:
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) { ... }
WYNIK:
źródło
Większość odpowiedzi była dobra i właściwa dla twojego problemu
Proponuję to bardzo proste i nieskomplikowane podejście, które gwarantuje prawidłową różnicę w dowolnej strefie czasowej:
int difference= ((int)((startDate.getTime()/(24*60*60*1000)) -(int)(endDate.getTime()/(24*60*60*1000))));
I to wszystko!
źródło
Użyj jodatime API
gdzie „start” i „end” to obiekty DateTime . Aby przeanalizować ciągi znaków daty w obiekty DateTime, użyj metody parseDateTime
Istnieje również biblioteka JodaTime dla systemu Android .
źródło
Ten fragment uwzględnia czas letni i wynosi 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)); }
źródło
To jest prosta i najlepsza kalkulacja dla mnie i może być dla Ciebie.
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); }
źródło
Odpowiedź
Correct Way
z Sam Quest działa tylko wtedy, gdy pierwsza data jest wcześniejsza niż druga. Co więcej, zwróci 1, jeśli dwie daty są w ciągu jednego dnia.To jest rozwiązanie, które najlepiej mi się sprawdziło. Podobnie jak większość innych rozwiązań, nadal pokazywałby nieprawidłowe wyniki przez dwa dni w roku z powodu niewłaściwego przesunięcia czasu oszczędzania światła dziennego.
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); }
źródło
najlepszy i najłatwiejszy sposób, aby to zrobić
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; }
źródło
tl; dr
ChronoUnit.DAYS.between( LocalDate.parse( "1999-12-28" ) , LocalDate.parse( "12/31/1999" , DateTimeFormatter.ofPattern( "MM/dd/yyyy" ) ) )
Detale
Inne odpowiedzi są nieaktualne. Stare klasy daty i godziny w pakiecie z najwcześniejszymi wersjami Javy okazały się źle zaprojektowane, zagmatwane i kłopotliwe. Unikaj ich.
java.time
Projekt Joda-Time odniósł duży sukces jako zamiennik dla tych starych klas. Klasy te stanowiły inspirację dla środowiska java.time wbudowanego w Javę 8 i nowszą.
Znaczna część funkcjonalności java.time jest przenoszona z powrotem do Javy 6 i 7 w ThreeTen-Backport i dalej dostosowywana do Androida w ThreeTenABP .
LocalDate
LocalDate
Klasa reprezentuje wartość data-tylko bez time-of-day i bez strefy czasowej.Parsowanie ciągów
Jeśli ciągi wejściowe są w standardowym formacie ISO 8601 ,
LocalDate
klasa może bezpośrednio przeanalizować ciąg.LocalDate start = LocalDate.parse( "1999-12-28" );
Jeśli nie jest w formacie ISO 8601, zdefiniuj wzorzec formatowania za pomocą
DateTimeFormatter
.String input = "12/31/1999"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MM/dd/yyyy" ); LocalDate stop = LocalDate.parse( input , formatter );
Upłynęło dni za pośrednictwem
ChronoUnit
Teraz oblicz liczbę dni, które upłynęły między tą parą
LocalDate
obiektów. DoChronoUnit
oblicza enum upływającego czasu.long totalDays = ChronoUnit.DAYS.between( start , stop ) ;
Jeśli nie jesteś zaznajomiony z wyliczeniami języka Java, wiedz, że są one znacznie bardziej wydajne i przydatne niż konwencjonalne wyliczenia w większości innych języków programowania. Zobacz
Enum
dokumentację zajęć, samouczek Oracle i Wikipedię, aby dowiedzieć się więcej.Informacje o java.time
Struktura java.time jest wbudowana w Javę 8 i nowsze. Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak
java.util.Date
,Calendar
, iSimpleDateFormat
.Projekt Joda-Time , obecnie w trybie konserwacji , zaleca migrację do klas java.time .
Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj Stack Overflow, aby znaleźć wiele przykładów i wyjaśnień. Specyfikacja to JSR 310 .
Skąd wziąć klasy java.time?
Projekt ThreeTen-Extra rozszerza java.time o dodatkowe klasy. Ten projekt jest poligonem doświadczalnym dla ewentualnych przyszłych dodatków do java.time. Można znaleźć kilka przydatnych klas tutaj takie jak
Interval
,YearWeek
,YearQuarter
, i więcej .źródło
Użyj następujących funkcji:
/** * 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; }
źródło
Jest proste rozwiązanie, które przynajmniej dla mnie jest jedynym możliwym rozwiązaniem.
Problem polega na tym, że wszystkie odpowiedzi, które widzę, są rzucane w kółko - używając Jody, Kalendarza, Daty lub czegokolwiek innego - uwzględniają tylko ilość milisekund. W końcu liczą liczbę 24-godzinnych cykli między dwiema datami , a nie faktyczną liczbę dni . Więc coś od 1 stycznia 23:00 do 2 stycznia 1:00 wróci 0 dni.
Aby policzyć faktyczną liczbę dni między
startDate
aendDate
, po prostu wykonaj:// 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;
Spowoduje to wyświetlenie wartości „1” między 2 a 1 stycznia. Jeśli chcesz policzyć dzień zakończenia, po prostu dodaj 1 do
daysBetween
(musiałem to zrobić w moim kodzie, ponieważ chciałem policzyć całkowitą liczbę dni w zakresie).Jest to trochę podobne do tego, co zasugerował Daniel, ale przypuszczam, że jest to mniejszy kod.
źródło
Wszystkie te rozwiązania mają jeden z dwóch problemów. Albo rozwiązanie nie jest idealnie dokładne z powodu błędów zaokrągleń, dni przestępnych i sekund itp., Albo w końcu zapętlasz liczbę dni między dwiema nieznanymi datami.
To rozwiązanie rozwiązuje pierwszy problem i poprawia drugi o współczynnik około 365, lepiej, jeśli wiesz, jaki jest Twój maksymalny zasięg.
/** * @param thisDate * @param thatDate * @param maxDays * set to -1 to not set a max * @returns number of days covered between thisDate and thatDate, inclusive, i.e., 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; }
Jeśli potrzebujesz dni między datami (nie licząc ostatniej daty), po prostu pozbądź się tego,
+ 1
kiedy zobaczyszendDay - startDay + 1
.źródło
W inny sposób:
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); }
źródło
korzystać z tych funkcji
public static int getDateDifference(int previousYear, int previousMonthOfYear, int previousDayOfMonth, int nextYear, int nextMonthOfYear, int nextDayOfMonth, int differenceToCount){ // int differenceToCount = can be any of the following // Calendar.MILLISECOND; // Calendar.SECOND; // Calendar.MINUTE; // Calendar.HOUR; // Calendar.DAY_OF_MONTH; // Calendar.MONTH; // Calendar.YEAR; // Calendar.---- Calendar previousDate = Calendar.getInstance(); previousDate.set(Calendar.DAY_OF_MONTH, previousDayOfMonth); // month is zero indexed so month should be minus 1 previousDate.set(Calendar.MONTH, previousMonthOfYear); previousDate.set(Calendar.YEAR, previousYear); Calendar nextDate = Calendar.getInstance(); nextDate.set(Calendar.DAY_OF_MONTH, previousDayOfMonth); // month is zero indexed so month should be minus 1 nextDate.set(Calendar.MONTH, previousMonthOfYear); nextDate.set(Calendar.YEAR, previousYear); return getDateDifference(previousDate,nextDate,differenceToCount); } public static int getDateDifference(Calendar previousDate,Calendar nextDate,int differenceToCount){ // int differenceToCount = can be any of the following // Calendar.MILLISECOND; // Calendar.SECOND; // Calendar.MINUTE; // Calendar.HOUR; // Calendar.DAY_OF_MONTH; // Calendar.MONTH; // Calendar.YEAR; // Calendar.---- //raise an exception if previous is greater than nextdate. if(previousDate.compareTo(nextDate)>0){ throw new RuntimeException("Previous Date is later than Nextdate"); } int difference=0; while(previousDate.compareTo(nextDate)<=0){ difference++; previousDate.add(differenceToCount,1); } return difference; }
źródło
java.time
pakietem są teraz starsze i należy ich unikać. Obejmuje toDate
iCalendar
oraz klasy java.sql. Zobacz samouczek Oracle.public void dateDifferenceExample() { // Set the date for both of the calendar instance GregorianCalendar calDate = new GregorianCalendar(2012, 10, 02,5,23,43); GregorianCalendar cal2 = new GregorianCalendar(2015, 04, 02); // Get the represented date in milliseconds long millis1 = calDate.getTimeInMillis(); long millis2 = cal2.getTimeInMillis(); // Calculate difference in milliseconds long diff = millis2 - millis1; // Calculate difference in seconds long diffSeconds = diff / 1000; // Calculate difference in minutes long diffMinutes = diff / (60 * 1000); // Calculate difference in hours long diffHours = diff / (60 * 60 * 1000); // Calculate difference in days long diffDays = diff / (24 * 60 * 60 * 1000); Toast.makeText(getContext(), ""+diffSeconds, Toast.LENGTH_SHORT).show(); }
źródło
Znalazłem bardzo łatwy sposób na zrobienie tego i właśnie tego używam w mojej aplikacji.
Powiedzmy, że masz daty w obiektach Time (lub cokolwiek innego, potrzebujemy tylko milisekund):
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 }
źródło
Joda-Time
Najlepszym sposobem jest użycie Joda-Time , bardzo udanej biblioteki open source, którą można dodać do swojego projektu.
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();
Jeśli używasz Android Studio , bardzo łatwo jest dodać czas joda. W pliku build.gradle (aplikacja):
dependencies { compile 'joda-time:joda-time:2.4' compile 'joda-time:joda-time:2.4' compile 'joda-time:joda-time:2.2' }
źródło
toString
naDuration
generuje ciąg znaków jedno z ISO 8601 standardowych formatachPnYnMnDTnHnMnS
. TeP
znaki na początku, podczas gdyT
oddziela rok-miesiąc-dni od godziny minuty-sekundy. TakP3D
jest trzy dni iP3DT12H
trzy i pół dnia.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));
źródło