การคำนวณความแตกต่างระหว่างสองอินสแตนซ์วันที่ของ Java


433

ฉันใช้java.util.DateคลาสJava ใน Scala และต้องการเปรียบเทียบDateวัตถุและเวลาปัจจุบัน ฉันรู้ว่าฉันสามารถคำนวณเดลต้าโดยใช้ getTime ():

(new java.util.Date()).getTime() - oldDate.getTime()

อย่างไรก็ตามสิ่งนี้ทำให้ฉันมีlongมิลลิวินาทีแทน มีวิธีที่ง่ายกว่าและดีกว่าในการหาเวลาเดลต้าหรือไม่?


10
ทำไมไม่มีเวลารัก joda มันเป็นตัวเลือกที่ดีที่สุดถ้าคุณจะจัดการกับวันที่ในจาวา
หมอโจนส์

7
โปรดตรวจสอบโซลูชันซับ 2 อันของฉันโดยไม่ใช้ Joda และให้ผลลัพธ์ใน TimeUnit ใด ๆ ที่stackoverflow.com/a/10650881/82609
Sebastien Lorber

2
อัปยศในทุกคนที่แนะนำให้เวลา Joda และไม่แนะนำให้คำตอบ Java จริง ...
Zizouz212

2
@ Zizouz212 เกี่ยวกับการแนะนำ Joda-Time คลาสวันที่แบบเก่าที่มาพร้อมกับ Java นั้นไม่ดีไม่ดีจริงไม่ดีมีการออกแบบไม่ดีสับสนและลำบาก แย่มากที่ Joda-Time ประสบความสำเร็จอย่างมากในฐานะตัวแทนของพวกเขา แย่มากที่แม้แต่ Sun / Oracle ก็ยอมแพ้และใช้แพ็คเกจ java.time เป็นส่วนหนึ่งของ Java 8 และใหม่กว่า คลาส java.time ได้รับแรงบันดาลใจจาก Joda-Time ทั้งสอง Joda เวลาและ java.time จะนำโดยคนคนเดียวกัน, สตีเฟ่น Colbourne ผมจะบอกว่า“อายใครใช้แนะนำของDate, CalendarและSimpleDateFormat
Basil Bourque

2
ในขณะที่ Joda เวลาอาจจะเป็นคำตอบที่ดีเมื่อคำถามถูกถามในวันนี้คำตอบที่ดีที่สุดสำหรับทุกคนที่สามารถใช้ Java 8 คือการใช้และjava.time.Period / หรือ Durationดูคำตอบเพรา Bourque ด้านล่าง
Ole VV

คำตอบ:


198

DateAPI ของJDK นั้นเสียอย่างน่าเสียดาย ผมขอแนะนำให้ใช้ห้องสมุด Joda เวลา

Joda Time มีแนวคิดของช่วงเวลา :

Interval interval = new Interval(oldTime, new Instant());

แก้ไข: โดยวิธีการ Joda มีสองแนวคิด: Intervalสำหรับการแสดงช่วงเวลาระหว่างสองเวลา (แทนเวลาระหว่าง 8:00 ถึง 10:00) และ a Durationที่แสดงถึงความยาวของเวลาโดยไม่มีขอบเขตเวลาจริง (เช่นแทนสองชั่วโมง!)

หากคุณสนใจเพียงการเปรียบเทียบเวลาการDateใช้งานส่วนใหญ่(รวมถึง JDK หนึ่ง) จะใช้Comparableอินเทอร์เฟซซึ่งช่วยให้คุณใช้Comparable.compareTo()


ครับ - คุณหมายถึงไม่ได้Comparable.compareTo() Comparable.compare()
Scott Morrison

Joda-Time มีสามคลาสเพื่อแสดงช่วงเวลาในรูปแบบต่างๆ: ช่วงเวลาช่วงเวลาและช่วงเวลา คำตอบที่ถูกต้องนี้กล่าวถึงสองคนแรกนี้ ดูคำตอบของฉันสำหรับข้อมูลเกี่ยวกับช่วงเวลา
Basil Bourque

Java 8 มีวันที่และเวลาใหม่เช่น apa joda
tbodt

11
java.timeแพ็คเกจใหม่ใน Java 8 ได้รับแรงบันดาลใจจาก Joda-Time แต่ไม่ใช่การแทนที่แบบดรอปอิน แต่ละคนมีข้อดีข้อเสีย โชคดีที่คุณไม่ต้องเลือกระหว่างพวกเขา ใช้แต่ละจุดแข็งของมันตราบใดที่คุณระมัดระวังในimportข้อความของคุณ ดูคำตอบอื่น ๆ นี้สำหรับตัวอย่างของ java.time
Basil Bourque

6
FYI โครงการJoda-Timeขณะนี้อยู่ในโหมดบำรุงรักษาโดยทีมงานให้คำแนะนำการย้ายถิ่นไปยังคลาสjava.time ดูการสอนโดยออราเคิล
Basil Bourque

550

Simple diff (ไม่มี lib)

/**
 * Get a diff between two dates
 * @param date1 the oldest date
 * @param date2 the newest date
 * @param timeUnit the unit in which you want the diff
 * @return the diff value, in the provided unit
 */
public static long getDateDiff(Date date1, Date date2, TimeUnit timeUnit) {
    long diffInMillies = date2.getTime() - date1.getTime();
    return timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS);
}

จากนั้นคุณสามารถโทร:

getDateDiff(date1,date2,TimeUnit.MINUTES);

เพื่อรับผลต่างของ 2 วันในหน่วยนาที

TimeUnitคือjava.util.concurrent.TimeUnitJava มาตรฐาน enum เริ่มจาก nanos เป็นวัน


ความแตกต่างที่มนุษย์สามารถอ่านได้ (ไม่มี lib)

public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {

    long diffInMillies = date2.getTime() - date1.getTime();

    //create the list
    List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
    Collections.reverse(units);

    //create the result map of TimeUnit and difference
    Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
    long milliesRest = diffInMillies;

    for ( TimeUnit unit : units ) {

        //calculate difference in millisecond 
        long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
        long diffInMilliesForUnit = unit.toMillis(diff);
        milliesRest = milliesRest - diffInMilliesForUnit;

        //put the result in the map
        result.put(unit,diff);
    }

    return result;
}

http://ideone.com/5dXeu6

เอาท์พุทเป็นสิ่งที่ต้องการMap:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}โดยหน่วยสั่ง

คุณเพียงแค่ต้องแปลงแผนที่นั้นเป็นสตริงที่ใช้งานง่าย


คำเตือน

ตัวอย่างโค้ดข้างต้นคำนวณผลต่างอย่างง่ายระหว่าง 2 instants มันอาจทำให้เกิดปัญหาในระหว่างการสลับเวลากลางวันเช่นอธิบายในโพสต์นี้ ซึ่งหมายความว่าหากคุณคำนวณส่วนต่างระหว่างวันที่โดยไม่มีเวลาคุณอาจมีวัน / ชั่วโมงที่ขาดหายไป

ในความคิดของฉันวันที่แตกต่างเป็นเรื่องส่วนตัวโดยเฉพาะในวันที่ คุณอาจ:

  • นับจำนวนเวลาที่ผ่านไป 24 ชั่วโมง: วัน + 1 - วัน = 1 วัน = 24 ชั่วโมง

  • นับจำนวนเวลาที่ผ่านไปดูแลการประหยัดเวลากลางวัน: วัน + 1 - วัน = 1 = 24 ชั่วโมง (แต่ใช้เวลาเที่ยงคืนและเวลาออมแสงอาจเป็น 0 วันและ 23 ชั่วโมง)

  • นับจำนวนday switchesซึ่งหมายถึงวัน + 1 13.00 น. - วัน 11.00 น. = 1 วันแม้ว่าเวลาที่ผ่านไปจะเป็นเพียง 2h (หรือ 1 ชั่วโมงหากมีการปรับเวลาตามฤดูกาล: p)

คำตอบของฉันถูกต้องถ้าคำจำกัดความของคุณวันที่แตกต่างกันตรงกับกรณีที่ 1

ด้วย JodaTime

หากคุณกำลังใช้ JodaTime คุณจะได้รับส่วนต่างสำหรับวันที่ 2 Instants (Millies แอ่น ReadableInstant) วันที่ด้วย:

Interval interval = new Interval(oldInstant, new Instant());

แต่คุณสามารถรับส่วนต่างสำหรับวันที่ / เวลาท้องถิ่น:

// returns 4 because of the leap year of 366 days
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5), PeriodType.years()).getYears() 

// this time it returns 5
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5+1), PeriodType.years()).getYears() 

// And you can also use these static methods
Years.yearsBetween(LocalDate.now(), LocalDate.now().plusDays(365*5)).getYears()

ว้าวคุณสามารถสอนเทคนิคใหม่แก่หมาตัวจริงได้! ไม่เคยได้ยินเรื่องนี้มาก่อนมีประโยชน์มากสำหรับการแปลความแตกต่างวันที่เป็นสตริงที่มีความหมาย
Jeremy Goodell

@SebastienLorber มีวิธีใน TimeUnit ในการคำนวณความแตกต่างดังนั้น "ตั้งปลุกได้ 3 วัน 4 ชั่วโมง 12 นาทีจากนี้"
likejudo

สิ่งที่ยอดเยี่ยมช่วยประหยัดเวลาของฉันได้มากจริงๆ ขอบคุณที่คุณช่วย.
Lyju I Edwinson

ฉันเสียชีวิต 3 วันในการจัดการกับ Java Dates และฉันก็ทิ้งมันไปเยอะและแทนที่ด้วยสิ่งนี้ ขอบคุณ.
user1091524

นี่เป็นคำตอบที่ดีที่สุดที่ฉันเคยเห็นตั้งแต่ฉันมาที่ stackoverflow! : D: D: D
Cold

153
int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime()) 
                 / (1000 * 60 * 60 * 24) )

โปรดทราบว่าการทำงานกับวันที่ UTC ดังนั้นความแตกต่างอาจเป็นวันหยุดถ้าคุณดูวันที่ท้องถิ่น และการทำให้การทำงานอย่างถูกต้องกับวันที่ในท้องถิ่นนั้นต้องใช้วิธีที่แตกต่างอย่างสิ้นเชิงเนื่องจากเวลาออมแสง


6
สิ่งนี้ใช้ไม่ได้จริงใน Android มีข้อผิดพลาดในการปัดเศษ ตัวอย่างที่ 19 ถึง 21 พฤษภาคมบอกว่า 1 วันเพราะมันใช้เวลา 1.99 ถึง 1 ใช้รอบก่อนที่จะทำการหล่อ
Pratik Mandrekar

4
นี่คือคำตอบที่ดีที่สุดและง่ายที่สุด เมื่อคำนวณความแตกต่างระหว่างสองวันที่โซนเวลาท้องถิ่นจะลบกัน ... เพื่อให้คำตอบที่ถูกต้อง (เป็นสองเท่า) นั้นได้รับเพียงแค่ ((สองครั้ง) (newer.getTime () - older.getTime ()) / (86400.0 * 1,000.0); ... เป็นสองครั้งคุณมีวันเศษส่วนเช่นกันซึ่งสามารถแปลงเป็น HH: MM: ss ได้อย่างง่ายดาย
scottb

8
@scottb: ปัญหาเกี่ยวกับวันที่ในท้องถิ่นคือคุณสามารถมีเวลาออมแสงในเวลากลางวันซึ่งหมายความว่าบางวันมี 23 หรือ 25 ชั่วโมงอาจทำให้ผลลัพธ์ล่าช้า
Michael Borgwardt

1
@ Steve: มันเป็น 28 สำหรับฉันเมื่อกำหนดพวกเขาเช่นวันที่ใหม่นี้ (115, 2, 26); (ให้ความสนใจกับเอกสาร API สำหรับพารามิเตอร์) เป็นไปได้หรือไม่ที่คุณแยกวิเคราะห์โดยใช้รูปแบบวันที่ของสหรัฐอเมริกาและในโหมดผ่อนปรนดังนั้น 26/03/2015 จึงถูกตีความว่าเป็นวันที่ 3 ของเดือนที่ 26 ของปี 2015?
Michael Borgwardt

1
@ Steve: อืมไม่แน่ใจว่าทำไมฉันถึงได้ผลลัพธ์ที่แตกต่างมาก่อน แต่ตอนนี้ฉันสามารถทำซ้ำข้อผิดพลาดของคุณ เครื่องมือจัดฟันในโค้ดของคุณแตกต่างจากคำตอบของฉันซึ่งทำให้(endDate.getTime() - startDate.getTime())ต้องส่งไปintแทนที่ผลลัพธ์สุดท้ายและคุณจะได้รับจำนวนเต็มล้น
Michael Borgwardt

54

การใช้เฟรมเวิร์กjava.time ที่สร้างขึ้นใน Java 8+:

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println("ISO-8601: " + duration);
System.out.println("Minutes: " + duration.toMinutes());

เอาท์พุท:

ISO-8601: PT24H10M

นาที: 1,450

สำหรับข้อมูลเพิ่มเติมโปรดดูที่ออราเคิลการสอนและการรับรองมาตรฐาน ISO 8601มาตรฐาน


5
สิ่งนี้หรือใช้PeriodแทนDurationวันที่
Aphex

53

คุณต้องกำหนดปัญหาของคุณให้ชัดเจนยิ่งขึ้น คุณสามารถใช้จำนวนมิลลิวินาทีระหว่างสองDateวัตถุและหารด้วยจำนวนมิลลิวินาทีใน 24 ชั่วโมงตัวอย่างเช่น ... แต่:

  • สิ่งนี้จะไม่นำการพิจารณาเขตเวลา - Dateอยู่ใน UTC เสมอ
  • สิ่งนี้จะไม่นำมาพิจารณาในการปรับเวลาตามฤดูกาล (ซึ่งอาจมีวันที่มีความยาวเพียง 23 ชั่วโมงเป็นต้น)
  • แม้ภายใน UTC จะมีกี่วันในวันที่ 16 สิงหาคมเวลา 23.00 น. ถึง 18.00 น. เพียง 27 ชั่วโมงดังนั้นนั่นหมายความว่าหนึ่งวัน? หรือควรเป็นสามวันเพราะครอบคลุมสามวัน?

1
ฉันคิดว่า java.util วันที่เป็นเพียงเสื้อคลุมเล็ก ๆ รอบการแสดงเวลาเป็นมิลลิวินาทีตีความในเขตเวลาท้องถิ่น (ค่าเริ่มต้น) การพิมพ์วันที่ให้ฉันเป็นตัวแทนเขตเวลาท้องถิ่น ฉันสับสนที่นี่
Adriaan Koster

46

TL; DR

แปลงล้าสมัยของวัตถุที่จะทดแทนของพวกเขาjava.util.Date แล้วคำนวณเวลาที่ผ่านไปเป็นjava.time.InstantDuration

Duration d = 
    Duration.between(                   // Calculate the span of time between two moments as a number of hours, minutes, and seconds.
        myJavaUtilDate.toInstant() ,    // Convert legacy class to modern class by calling new method added to the old class.
        Instant.now()                   // Capture the current moment in UTC. About two and a half hours later in this example.
    )
;

d.toString (): PT2H34M56S

d.toMinutes (): 154

d.toMinutesPart (): 34

รูปแบบ ISO 8601: PnYnMnDTnHnMnS

สมเหตุสมผลมาตรฐานISO 8601กำหนดเป็นตัวแทนกระชับต้นฉบับเดิมของช่วงเวลาที่เป็นตัวเลขของปีเดือนวันชั่วโมง ฯลฯ มาตรฐานสายดังกล่าวคืบดังกล่าวเป็นระยะเวลา รูปแบบคือPnYnMnDTnHnMnSที่Pหมายถึง "ระยะเวลา" ส่วนที่Tแยกวันที่จากส่วนเวลาและในระหว่างนั้นเป็นตัวเลขตามด้วยตัวอักษร

ตัวอย่าง:

  • P3Y6M4DT12H30M5S
    สามปีหกเดือนสี่วันสิบสองชั่วโมงสามสิบนาทีและห้าวินาที
  • PT4H30M
    สี่ชั่วโมงครึ่ง

java.time

java.timeกรอบที่สร้างขึ้นใน Java 8 และต่อมา supplants ลำบากเก่าjava.util.Date/ java.util.Calendarชั้นเรียน คลาสใหม่นี้ได้รับแรงบันดาลใจจากกรอบการทำงานของJoda-Time ที่ประสบความสำเร็จอย่างสูงซึ่งมีจุดประสงค์เพื่อเป็นตัวตายตัวแทนซึ่งคล้ายกับแนวคิด แต่ได้รับการออกแบบใหม่ กำหนดโดยJSR 310 ขยายโดยThreeTen-พิเศษโครงการ ดูการสอน

ขณะ

Instantชั้นหมายถึงช่วงเวลาบนไทม์ไลน์ในส่วนUTCมีความละเอียดของนาโนวินาที (ถึงเก้า (9) ตัวเลขของส่วนทศนิยม)

Instant instant = Instant.now() ;  // Capture current moment in UTC.

ที่ดีที่สุดเพื่อหลีกเลี่ยงการเรียนแบบเดิมเช่น/Date Calendarแต่ถ้าคุณต้องทำงานร่วมกับรหัสเก่าที่ยังไม่ได้อัปเดตเป็นjava.timeให้แปลงไปมา เรียกวิธีการแปลงใหม่ที่เพิ่มในคลาสเก่า สำหรับการย้ายจากjava.util.DateไปยังโทรInstantDate::toInstant

Instant instant = myJavaUtilDate.toInstant() ;  // Convert from legacy `java.util.Date` class to modern `java.time.Instant` class.

ช่วงเวลา

คลาส java.time ได้แบ่งแนวคิดนี้ในการแสดงช่วงเวลาเป็นจำนวนปี, เดือน, วัน, ชั่วโมง, นาที, วินาทีเป็นสองส่วน:

  • Period สำหรับปีเดือนวัน
  • Duration สำหรับวันชั่วโมงนาทีวินาที

นี่คือตัวอย่าง

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime future = now.plusMinutes ( 63 );
Duration duration = Duration.between ( now , future );

ถ่ายโอนข้อมูลไปยังคอนโซล

ทั้งสองPeriodและDurationใช้มาตรฐาน ISO 8601สำหรับการสร้างการแสดงสตริงของค่าของพวกเขา

System.out.println ( "now: " + now + " to future: " + now + " = " + duration );

ตอนนี้: 2015-11-26T00: 46: 48.016-05: 00 [อเมริกา / มอนทรีออล] ถึงอนาคต: 2015-11-26T00: 46: 48.016-05: 00 [อเมริกา / มอนทรีออล] = PT1H3M

Java 9 เพิ่มวิธีการเพื่อDurationให้ได้ส่วนวันส่วนชั่วโมงส่วนนาทีและส่วนวินาที

คุณสามารถรับจำนวนวันหรือชั่วโมงหรือนาทีหรือวินาทีหรือวินาทีหรือมิลลิวินาทีหรือ nanoseconds ในระยะเวลาทั้งหมด

long totalHours = duration.toHours();

ใน Java 9 Durationคลาสจะได้รับวิธีการใหม่ในการคืนส่วนต่าง ๆ ของวันชั่วโมงนาทีวินาทีวินาทีมิลลิวินาที / นาโนวินาที เรียกto…Partวิธีการ: toDaysPart(), toHoursPart()และอื่น ๆ

ChronoUnit

หากคุณสนใจว่าจะมีเวลามากขึ้นอย่างง่ายเช่น "จำนวนวันที่ผ่านไป" ให้ใช้ChronoUnitenum

long daysElapsed = ChronoUnit.DAYS.between( earlier , later );

ตัวอย่างอื่น.

Instant now = Instant.now();
Instant later = now.plus( Duration.ofHours( 2 ) );

long minutesElapsed = ChronoUnit.MINUTES.between( now , later );

120


เกี่ยวกับ java.time

java.timeกรอบถูกสร้างขึ้นใน Java 8 และต่อมา ชั้นเรียนเหล่านี้แย่งลำบากเก่ามรดกเรียนวันที่เวลาเช่นjava.util.Date, และCalendarSimpleDateFormat

Joda เวลาโครงการขณะนี้อยู่ในโหมดการบำรุงรักษาให้คำแนะนำแก่การโยกย้ายไปยัง java.time

ต้องการเรียนรู้เพิ่มเติมโปรดดูที่ออราเคิลกวดวิชา และค้นหา Stack Overflow สำหรับตัวอย่างและคำอธิบายมากมาย สเปกJSR 310

จะรับคลาส java.time ได้ที่ไหน?

  • Java SE 8และ SE 9และใหม่กว่า
    • Built-in
    • เป็นส่วนหนึ่งของ Java API มาตรฐานที่มีการใช้งานแบบรวม
    • Java 9 เพิ่มคุณสมบัติและการแก้ไขเล็กน้อย
  • Java SE 6และ SE 7
    • มากของการทำงาน java.time จะกลับรังเพลิง Java 6 และ 7 ในThreeTen-ย้ายกลับ
  • Android

โครงการThreeTen-Extraขยาย java.time ด้วยคลาสเพิ่มเติม โครงการนี้เป็นพื้นฐานที่พิสูจน์ได้สำหรับการเพิ่มเติมในอนาคตไปยัง java.time คุณอาจพบว่าการเรียนที่มีประโยชน์บางอย่างที่นี่เช่นInterval, YearWeek, YearQuarterและอื่น ๆ อีกมากมาย


Joda เวลา

UPDATE: โครงการJoda-Timeอยู่ในโหมดบำรุงรักษาโดยทีมงานจะแนะนำการย้ายไปยังคลาสjava.time ฉันจะปล่อยให้ส่วนนี้ไม่เสียหายสำหรับประวัติ

ไลบรารี Joda-Time ใช้ ISO 8601 เป็นค่าเริ่มต้น มันPeriodจะแยกวิเคราะห์ระดับและสร้างเหล่านี้สตริง PnYnMnDTnHnMnS

DateTime now = DateTime.now(); // Caveat: Ignoring the important issue of time zones.
Period period = new Period( now, now.plusHours( 4 ).plusMinutes( 30));
System.out.println( "period: " + period );

วาทกรรม:

period: PT4H30M

เป็นเรื่องตลกที่คุณเริ่มต้นกำแพงข้อความที่ไม่เกี่ยวข้องกับคำถามด้วย "tl; dr" คำถามไม่ได้เกี่ยวกับวิธีการบันทึกเวลาจาก X ที่ผ่านมาหรือในหน่วย X เวลา แต่วิธีการรับ delta ระหว่างสองวัน แค่นั้นแหละ.
บัฟฟาโล่

@Buffalo ฉันไม่เข้าใจความคิดเห็นของคุณ คำตอบของฉันเกี่ยวข้องกับPeriod, DurationและChronoUnit, สามคลาสที่มีจุดประสงค์เพื่อกำหนดเดลต้าระหว่างจุดเวลา โปรดระบุว่าส่วนใดของ "ข้อความผนัง" ของฉันที่ไม่เกี่ยวข้อง และคุณไม่ถูกต้องในการพูดคำถามที่ถามถึง "เดลต้าระหว่างวันที่": คำถามที่ถามเดลต้าระหว่างDateวัตถุซึ่งเป็นช่วงเวลาที่วันที่ไม่ใช่ "วันที่" แม้จะมีการตั้งชื่อที่โชคร้ายของคลาสนั้น
Basil Bourque

ไม่มีความคิดเห็นของคุณในการจัดการวัตถุ java.util.Date ที่มีอยู่สองรายการ ฉันลองใช้ตัวอย่างในรหัสของฉันและไม่พบสิ่งใดที่ใช้วัตถุ java.util.Date
บัฟฟาโล่

@Buffalo ยุติธรรมพอคำวิจารณ์ที่ดี ฉันเพิ่มโค้ดในส่วน "tl; dr" ที่แปลงจาก a java.util.Dateเป็นInstant(เพียงแค่เรียก.toInstant) และฉันได้เพิ่มMomentหัวข้อเพื่ออธิบาย คุณพูดถึงคู่ของDateวัตถุ แต่จริงๆแล้วคำถามใช้เพียงDateวัตถุเดียวที่มีอยู่แล้วจับช่วงเวลาปัจจุบันดังนั้นฉันจึงทำเช่นเดียวกัน ขอบคุณสำหรับความคิดเห็น! เคล็ดลับ: เลิกใช้Date- คลาสดั้งเดิมนั้นยุ่งเหยิงอย่างยิ่งยวด
Basil Bourque


23

ทางเลือกที่ง่ายกว่าเล็กน้อย:

System.currentTimeMillis() - oldDate.getTime()

สำหรับ "ดีกว่า": คุณต้องการอะไรอย่างแน่นอน ปัญหาเกี่ยวกับการแสดงช่วงเวลาเป็นจำนวนชั่วโมงและวันอื่น ๆ คืออาจนำไปสู่ความไม่ถูกต้องและความคาดหวังที่ไม่ถูกต้องเนื่องจากความซับซ้อนของวันที่ (เช่นวันสามารถมี 23 หรือ 25 ชั่วโมงเนื่องจากเวลาออมแสง)


22

การใช้วิธีการมิลลิวินาทีอาจทำให้เกิดปัญหาในบางภาษา

ยกตัวอย่างเช่นความแตกต่างระหว่างสองวันที่ 03/24/2007 และ 03/25/2007 ควรเป็น 1 วัน

อย่างไรก็ตามการใช้เส้นทางมิลลิวินาทีคุณจะได้รับ 0 วันหากคุณใช้เส้นทางนี้ในสหราชอาณาจักร!

/** Manual Method - YIELDS INCORRECT RESULTS - DO NOT USE**/  
/* This method is used to find the no of days between the given dates */  
public long calculateDays(Date dateEarly, Date dateLater) {  
   return (dateLater.getTime() - dateEarly.getTime()) / (24 * 60 * 60 * 1000);  
} 

วิธีที่ดีกว่าในการใช้งานนี้คือการใช้ java.util.Calendar

/** 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;  
}  

19
คุณช่วยให้เครดิตผู้เขียนต้นฉบับของรหัสนี้และประโยคที่สามซึ่งมีรายการบล็อกลงวันที่ปี 2007 ได้หรือไม่
wchargin

มันไม่ได้ผลหรือเปล่า?
Gangnus

มันทำงานไม่ถูกต้อง วันระหว่าง (ใหม่ GregorianCalendar (2014,03,01), ใหม่ GregorianCalendar (2014,04,02))); ส่งคืน 31 และมันควรกลับ 32: timeanddate.com/date/…
marcolopes

5
@marcolopes - คุณผิด - เพราะเดือนตามปฏิทินเป็นศูนย์ ฉันแน่ใจว่าคุณหมายถึง march / april แต่สิ่งที่คุณทดสอบคือ april / june ซึ่งคือ 31. เพื่อให้ปลอดภัยเขียนเช่น -> GregorianCalendar ใหม่ (2014, Calendar.MARCH, 1) ....
ลุง Iroh

@ UncleIroh คุณพูดถูก! ฉันพลาดความจริงที่สำคัญ (เดือนตามปฏิทินนั้นไม่มีศูนย์) ฉันต้องทบทวนคำถามนี้อีกครั้ง
marcolopes

22

มีหลายวิธีที่คุณสามารถค้นหาความแตกต่างระหว่างวันที่และเวลา หนึ่งในวิธีที่ง่ายที่สุดที่ฉันรู้คือ:

      Calendar calendar1 = Calendar.getInstance();
      Calendar calendar2 = Calendar.getInstance();
      calendar1.set(2012, 04, 02);
      calendar2.set(2012, 04, 04);
      long milsecs1= calendar1.getTimeInMillis();
      long milsecs2 = calendar2.getTimeInMillis();
      long diff = milsecs2 - milsecs1;
      long dsecs = diff / 1000;
      long dminutes = diff / (60 * 1000);
      long dhours = diff / (60 * 60 * 1000);
      long ddays = diff / (24 * 60 * 60 * 1000);

      System.out.println("Your Day Difference="+ddays);

คำสั่งพิมพ์เป็นเพียงตัวอย่าง - คุณสามารถจัดรูปแบบตามที่คุณต้องการ


5
@ manoj kumar bardhan: ยินดีต้อนรับสู่กองล้น: ตามที่คุณเห็นคำถามและคำตอบคือปีเก่า คำตอบของคุณควรเพิ่มคำถาม / คำตอบมากกว่าคำตอบเดิม
Jayan

3
แล้ววันไหนที่มี 23 หรือ 25 ชั่วโมงเนื่องจากการเปลี่ยน DST?
Joni

19

เนื่องจากคำตอบทั้งหมดที่นี่มีความถูกต้อง แต่ใช้ java ดั้งเดิมหรือ libs บุคคลที่สามเช่น joda หรือคล้ายกันฉันจะทิ้งอีกวิธีหนึ่งโดยใช้คลาสjava.timeใหม่ใน Java 8 และใหม่กว่า ดูออราเคิลกวดวิชา

ใช้LocalDateและChronoUnit:

LocalDate d1 = LocalDate.of(2017, 5, 1);
LocalDate d2 = LocalDate.of(2017, 5, 18);

long days = ChronoUnit.DAYS.between(d1, d2);
System.out.println( days );

9

การลบวันที่เป็นมิลลิวินาที (ตามที่อธิบายในโพสต์อื่น) แต่คุณต้องใช้ HOUR_OF_DAY และไม่ใช่ HOUR เมื่อทำการล้างส่วนของวันที่:

public static final long MSPERDAY = 60 * 60 * 24 * 1000;
...
final Calendar dateStartCal = Calendar.getInstance();
dateStartCal.setTime(dateStart);
dateStartCal.set(Calendar.HOUR_OF_DAY, 0); // Crucial.
dateStartCal.set(Calendar.MINUTE, 0);
dateStartCal.set(Calendar.SECOND, 0);
dateStartCal.set(Calendar.MILLISECOND, 0);
final Calendar dateEndCal = Calendar.getInstance();
dateEndCal.setTime(dateEnd);
dateEndCal.set(Calendar.HOUR_OF_DAY, 0); // Crucial.
dateEndCal.set(Calendar.MINUTE, 0);
dateEndCal.set(Calendar.SECOND, 0);
dateEndCal.set(Calendar.MILLISECOND, 0);
final long dateDifferenceInDays = ( dateStartCal.getTimeInMillis()
                                  - dateEndCal.getTimeInMillis()
                                  ) / MSPERDAY;
if (dateDifferenceInDays > 15) {
    // Do something if difference > 15 days
}

1
วิธีนี้เป็นวิธีที่ดีที่สุดในการกำหนดความแตกต่างระหว่างสองวันที่ในปฏิทินโดยไม่ต้องไปอยู่นอกไลบรารีมาตรฐาน คำตอบอื่น ๆ ส่วนใหญ่ถือว่าต่อวันเป็นระยะเวลา 24 ชั่วโมงโดยพลการ หากเผ่นวินาทีถูกลบมากกว่าเพิ่มการคำนวณขั้นสุดท้ายอาจถูกปิดโดยหนึ่งเนื่องจากการตัดทอนเนื่องจากความแตกต่างสัมบูรณ์อาจน้อยกว่าจำนวนทวีคูณของ MSPERDAY ทั้งหมดเล็กน้อย
JulianSymes

8

หากคุณไม่ต้องการใช้ JodaTime หรือวิธีอื่นที่คล้ายคลึงกันทางออกที่ดีที่สุดน่าจะเป็น:

final static long MILLIS_PER_DAY = 24 * 3600 * 1000;
long msDiff= date1.getTime() - date2.getTime();
long daysDiff = Math.round(msDiff / ((double)MILLIS_PER_DAY));

จำนวน ms ต่อวันนั้นไม่เหมือนกันเสมอไป (เนื่องจากการปรับเวลาตามฤดูกาลและการกระโดดวินาที) แต่ใกล้เคียงกันมากและอย่างน้อยส่วนเบี่ยงเบนเนื่องจากการปรับเวลาตามฤดูกาลถูกยกเลิกในช่วงเวลาที่นานกว่า ดังนั้นการหารแล้วการปัดเศษจะให้ผลลัพธ์ที่ถูกต้อง (อย่างน้อยตราบใดที่ปฏิทินในเครื่องที่ใช้ไม่มีการกระโดดเวลาแปลก ๆ นอกเหนือจาก DST และวินาทีกระโดด)

โปรดทราบว่านี่ยังถือว่าdate1และdate2ตั้งเวลาเดียวกันของวัน สำหรับช่วงเวลาที่แตกต่างกันของวันคุณต้องกำหนดความหมายของ "ความแตกต่างของวันที่" ก่อนโดย Jon Skeet


ปัญหาก็คือในVSdate1.getTime() date2.getTime()ดังนั้นความแตกต่าง 2016-03-03 ถึง 2016-03-31 จะคำนวณ 27 วันในขณะที่คุณต้องการ 28 วัน
malat

@malat: ขออภัยฉันไม่สามารถติดตามได้ ฉันแค่ลองมัน - diffing 2016-03-03 ถึง 2016-03-31 ด้วยรหัสของฉันคำนวณ 28 วัน หากคำนวณอย่างอื่นในตัวอย่างของคุณให้ลองถามคำถามนั้นเป็นคำถามแยกต่างหาก
sleske

นอกจากนี้คุณได้อ่านข้อแม้ของฉันหรือไม่ "ยังคงถือว่าวันที่ 1 และวันที่ 2 ถูกตั้งค่าเป็นเวลาเดียวกันของวัน" คุณอาจใช้เวลาที่แตกต่างกันของวันในการทดสอบของคุณ?
sleske

ใช่แล้ว! ฉันพลาดเคล็ดลับMath.round()ที่ดูเหมือนว่าปลอดภัยในปฏิทิน 'โลกแห่งความจริง' ขอโทษสำหรับเสียงรบกวน
malat

8

ดูJoda Timeซึ่งเป็น API วันที่ / เวลาที่ปรับปรุงแล้วสำหรับ Java และควรทำงานได้ดีกับ Scala


ถูกแทนที่ด้วย java.time (JSR-310) ใน Java 8
malat

5

ให้ฉันแสดงความแตกต่างระหว่างช่วงเวลา Joda กับวัน:

DateTime start = new DateTime(2012, 2, 6, 10, 44, 51, 0);
DateTime end = new DateTime(2012, 2, 6, 11, 39, 47, 1);
Interval interval = new Interval(start, end);
Period period = interval.toPeriod();
System.out.println(period.getYears() + " years, " + period.getMonths() + " months, " + period.getWeeks() + " weeks, " + period.getDays() + " days");
System.out.println(period.getHours() + " hours, " + period.getMinutes() + " minutes, " + period.getSeconds() + " seconds ");
//Result is:
//0 years, 0 months, *1 weeks, 1 days*
//0 hours, 54 minutes, 56 seconds 

//Period can set PeriodType,such as PeriodType.yearMonthDay(),PeriodType.yearDayTime()...
Period p = new Period(start, end, PeriodType.yearMonthDayTime());
System.out.println(p.getYears() + " years, " + p.getMonths() + " months, " + p.getWeeks() + " weeks, " + p.getDays() + "days");
System.out.println(p.getHours() + " hours, " + p.getMinutes() + " minutes, " + p.getSeconds() + " seconds ");
//Result is:
//0 years, 0 months, *0 weeks, 8 days*
//0 hours, 54 minutes, 56 seconds 

5

หากคุณต้องการสตริงการส่งคืนที่จัดรูปแบบเช่น "2 วัน 03h 42m 07s" ลองสิ่งนี้:

public String fill2(int value)
{
    String ret = String.valueOf(value);

    if (ret.length() < 2)
        ret = "0" + ret;            
    return ret;
}

public String get_duration(Date date1, Date date2)
{                   
    TimeUnit timeUnit = TimeUnit.SECONDS;

    long diffInMilli = date2.getTime() - date1.getTime();
    long s = timeUnit.convert(diffInMilli, TimeUnit.MILLISECONDS);

    long days = s / (24 * 60 * 60);
    long rest = s - (days * 24 * 60 * 60);
    long hrs = rest / (60 * 60);
    long rest1 = rest - (hrs * 60 * 60);
    long min = rest1 / 60;      
    long sec = s % 60;

    String dates = "";
    if (days > 0) dates = days + " Days ";

    dates += fill2((int) hrs) + "h ";
    dates += fill2((int) min) + "m ";
    dates += fill2((int) sec) + "s ";

    return dates;
}

2
ถ้าอย่างนั้นทำไมคุณต้องม้วนเมื่อJoda-Timeจัดเตรียมคลาสของช่วงเวลาที่เขียนและดีบั๊กอยู่แล้ว?
Basil Bourque

8
เหตุใดฉันจึงควรดาวน์โหลด Library ที่มีขนาดไฟล์ที่บีบอัด 4.1 MB และเพิ่มลงในโครงการของฉันเมื่อฉันต้องการรหัส 32 บรรทัดเท่านั้น ???
Ingo

1
เพราะ Joda-Time เปรียบเหมือนมันฝรั่งทอดคุณไม่สามารถกินได้เพียงอันเดียว คุณจะใช้ Joda-Time ทั่วทุกที่ และเนื่องจาก Joda-Time นั้นผ่านการทดสอบและใส่รหัสอย่างดี และเนื่องจาก Joda-Time แยกวิเคราะห์และสร้างสตริงISO 8601 Durationมาตรฐานซึ่งอาจเป็นประโยชน์สำหรับการทำให้เป็นอนุกรมหรือการรายงานค่าเหล่านี้ และเนื่องจาก Joda-Time มีตัวจัดรูปแบบเพื่อพิมพ์ค่าที่เป็นตัวแทนของภาษาเหล่านี้
Basil Bourque

มีการทดสอบรหัสของคุณไม่ครบ stdข้างต้นไม่ได้กำหนด
Basil Bourque

@Basil Bourque: ขอบคุณสำหรับคำใบ้ ฉันแก้ไขแหล่งที่มา ข้อผิดพลาดนี้มาจากการแปลเป็นภาษาอังกฤษ
Ingo

5

หมายเหตุ: startDate และ endDates คือ -> java.util.Date

import org.joda.time.Duration;
import org.joda.time.Interval;
// Use .getTime() unless it is a joda DateTime object
Interval interval = new Interval(startDate.getTime(), endDate.getTime());
Duration period = interval.toDuration();
//gives the number of days elapsed between start 
period.getStandardDays();

และวันที่สิ้นสุด

เช่นเดียวกับวันคุณสามารถรับชั่วโมงนาทีและวินาที

period.getStandardHours();
period.getStandardMinutes();
period.getStandardSeconds();

4

ตรวจสอบตัวอย่างได้ที่นี่http://www.roseindia.net/java/beginners/DateDifferent.shtml ตัวอย่างนี้ให้ความแตกต่างในวันชั่วโมงนาทีวินาทีวินาทีและมิลลิวินาทีวินาที :)

import java.util.Calendar;
import java.util.Date;

public class DateDifferent {
    public static void main(String[] args) {
        Date date1 = new Date(2009, 01, 10);
        Date date2 = new Date(2009, 07, 01);
        Calendar calendar1 = Calendar.getInstance();
        Calendar calendar2 = Calendar.getInstance();
        calendar1.setTime(date1);
        calendar2.setTime(date2);
        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.");
    }
}

3
-1 ไม่ถูกต้องเว้นแต่ว่าอินสแตนซ์วันที่ได้รับมาจากเวลา UTC ดูคำตอบของ Jon Skeet
sleske

4

ใช้เขตเวลา GMT เพื่อรับอินสแตนซ์ของปฏิทินตั้งเวลาโดยใช้วิธีการตั้งค่าของคลาสปฏิทิน เขตเวลา GMT มีการชดเชย 0 (ไม่สำคัญ) และตั้งค่าสถานะการปรับเวลาตามฤดูกาลเป็นเท็จ

    final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

    cal.set(Calendar.YEAR, 2011);
    cal.set(Calendar.MONTH, 9);
    cal.set(Calendar.DAY_OF_MONTH, 29);
    cal.set(Calendar.HOUR, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    final Date startDate = cal.getTime();

    cal.set(Calendar.YEAR, 2011);
    cal.set(Calendar.MONTH, 12);
    cal.set(Calendar.DAY_OF_MONTH, 21);
    cal.set(Calendar.HOUR, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    final Date endDate = cal.getTime();

    System.out.println((endDate.getTime() - startDate.getTime()) % (1000l * 60l * 60l * 24l));

อย่าลืมให้ศูนย์เป็นมิลลิวินาทีส่วนอื่นเป็นคำตอบที่ดีในบริบทของคลาสเก่าjava.util.Dateและอื่น ๆ การใช้แฮ็คเพื่อตั้งค่าเขตเวลาเป็น GMT ทำให้โค้ดไม่ตอบสนองต่อการปรับเวลาตามฤดูกาล
Meno Hochschild

4

รหัสต่อไปนี้สามารถให้ผลลัพธ์ที่ต้องการ:

String startDate = "Jan 01 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy");
LocalDate date = LocalDate.parse(startDate, formatter);

String currentDate = "Feb 11 2015";
LocalDate date1 = LocalDate.parse(currentDate, formatter);

System.out.println(date1.toEpochDay() - date.toEpochDay());

3
คุณช่วยอธิบายได้ว่าโค้ดของคุณทำอะไรได้บ้าง? ดูเหมือนคำถามจะถามเกี่ยวกับช่วงเวลาหนึ่งและในทันทีที่เห็นรหัสของคุณจะกลับมาเป็นรูปสามเหลี่ยมวัน?
GHC

4
public static String getDifferenceBtwTime(Date dateTime) {

    long timeDifferenceMilliseconds = new Date().getTime() - dateTime.getTime();
    long diffSeconds = timeDifferenceMilliseconds / 1000;
    long diffMinutes = timeDifferenceMilliseconds / (60 * 1000);
    long diffHours = timeDifferenceMilliseconds / (60 * 60 * 1000);
    long diffDays = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24);
    long diffWeeks = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 7);
    long diffMonths = (long) (timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 30.41666666));
    long diffYears = (long)(timeDifferenceMilliseconds / (1000 * 60 * 60 * 24 * 365));

    if (diffSeconds < 1) {
        return "one sec ago";
    } else if (diffMinutes < 1) {
        return diffSeconds + " seconds ago";
    } else if (diffHours < 1) {
        return diffMinutes + " minutes ago";
    } else if (diffDays < 1) {
        return diffHours + " hours ago";
    } else if (diffWeeks < 1) {
        return diffDays + " days ago";
    } else if (diffMonths < 1) {
        return diffWeeks + " weeks ago";
    } else if (diffYears < 12) {
        return diffMonths + " months ago";
    } else {
        return diffYears + " years ago";
    }
}   

3
int daysDiff = (date1.getTime() - date2.getTime()) / MILLIS_PER_DAY;

5
-1 ไม่ถูกต้องเว้นแต่ว่าอินสแตนซ์วันที่ได้รับมาจากเวลา UTC ดูคำตอบของ Jon Skeet
sleske

5
@Sleske คุณไม่ถูกต้อง เขาได้สูญเสียข้อมูลเขตเวลาโดยใช้Dateดังนั้นการเปรียบเทียบนี้เป็นสิ่งที่ดีที่สุดที่สามารถทำได้ในสถานการณ์
Bozho

1
ตกลงเดาว่าเราทั้งคู่ถูกต้องแล้ว เป็นความจริงที่ขึ้นอยู่กับว่าอินสแตนซ์ Date มาจากไหน ถึงกระนั้นก็เป็นข้อผิดพลาดทั่วไปที่ควรจะกล่าวถึง
sleske

เมื่อฉันใช้โซลูชันของคุณจะมีข้อความแจ้งว่า: Type mismatch: ไม่สามารถแปลงจาก long เป็น int ได้ ฉันคิดว่าคุณควรเพิ่มการคัดเลือกนักแสดงหรือฉันขาดอะไรไปบ้าง?
Ad Infinitum

3

สิ่งที่ดีที่สุดที่จะทำคือ

(Date1-Date2)/86 400 000 

ตัวเลขนั้นคือจำนวนมิลลิวินาทีในหนึ่งวัน

วันที่อื่นวันที่ให้ความแตกต่างเป็นมิลลิวินาที

รวบรวมคำตอบในตัวแปรคู่


ใช่ทำไมไม่ ฉันไม่เข้าใจประเด็นของคำถามในบางวิธี: OP มีความแตกต่างใน ms ... และมีจำนวน ms ในหนึ่งวัน (ตกลงกับการปรับทางดาราศาสตร์บางครั้งในดวงจันทร์สีน้ำเงิน แต่ OP ไม่ได้ บอกได้ว่ามันต้องแม่นยำอย่างที่นักดาราศาสตร์ต้องการ ... )
mike rodent

3

นี่คือโซลูชัน Java 7 ที่ถูกต้องใน O (1) โดยไม่มีการอ้างอิงใด ๆ

public static int countDaysBetween(Date date1, Date date2) {

    Calendar c1 = removeTime(from(date1));
    Calendar c2 = removeTime(from(date2));

    if (c1.get(YEAR) == c2.get(YEAR)) {

        return Math.abs(c1.get(DAY_OF_YEAR) - c2.get(DAY_OF_YEAR)) + 1;
    }
    // ensure c1 <= c2
    if (c1.get(YEAR) > c2.get(YEAR)) {
        Calendar c = c1;
        c1 = c2;
        c2 = c;
    }
    int y1 = c1.get(YEAR);
    int y2 = c2.get(YEAR);
    int d1 = c1.get(DAY_OF_YEAR);
    int d2 = c2.get(DAY_OF_YEAR);

    return d2 + ((y2 - y1) * 365) - d1 + countLeapYearsBetween(y1, y2) + 1;
}

private static int countLeapYearsBetween(int y1, int y2) {

    if (y1 < 1 || y2 < 1) {
        throw new IllegalArgumentException("Year must be > 0.");
    }
    // ensure y1 <= y2
    if (y1 > y2) {
        int i = y1;
        y1 = y2;
        y2 = i;
    }

    int diff = 0;

    int firstDivisibleBy4 = y1;
    if (firstDivisibleBy4 % 4 != 0) {
        firstDivisibleBy4 += 4 - (y1 % 4);
    }
    diff = y2 - firstDivisibleBy4 - 1;
    int divisibleBy4 = diff < 0 ? 0 : diff / 4 + 1;

    int firstDivisibleBy100 = y1;
    if (firstDivisibleBy100 % 100 != 0) {
        firstDivisibleBy100 += 100 - (firstDivisibleBy100 % 100);
    }
    diff = y2 - firstDivisibleBy100 - 1;
    int divisibleBy100 = diff < 0 ? 0 : diff / 100 + 1;

    int firstDivisibleBy400 = y1;
    if (firstDivisibleBy400 % 400 != 0) {
        firstDivisibleBy400 += 400 - (y1 % 400);
    }
    diff = y2 - firstDivisibleBy400 - 1;
    int divisibleBy400 = diff < 0 ? 0 : diff / 400 + 1;

    return divisibleBy4 - divisibleBy100 + divisibleBy400;
}


public static Calendar from(Date date) {

    Calendar c = Calendar.getInstance();
    c.setTime(date);

    return c;
}


public static Calendar removeTime(Calendar c) {

    c.set(HOUR_OF_DAY, 0);
    c.set(MINUTE, 0);
    c.set(SECOND, 0);
    c.set(MILLISECOND, 0);

    return c;
}

2

นั่นอาจเป็นวิธีที่ตรงไปตรงมาที่สุดในการทำ - บางทีอาจเป็นเพราะฉันได้รับการเข้ารหัสใน Java (ด้วยวันที่และเวลาที่เป็นที่ยอมรับของห้องสมุด) ในขณะนี้ แต่รหัสนั้นดูง่ายและดีสำหรับฉัน!

คุณพอใจกับผลลัพธ์ที่ส่งคืนเป็นมิลลิวินาทีหรือเป็นส่วนหนึ่งของคำถามที่คุณต้องการให้ส่งคืนในรูปแบบอื่นหรือไม่


2

ไม่ได้ใช้ API มาตรฐานไม่ คุณสามารถม้วนตัวเองทำสิ่งนี้:

class Duration {
    private final TimeUnit unit;
    private final long length;
    // ...
}

หรือคุณสามารถใช้Joda :

DateTime a = ..., b = ...;
Duration d = new Duration(a, b);

2

เพียงตอบคำถามเริ่มต้น:

ใส่รหัสต่อไปนี้ในฟังก์ชั่นเช่น Long getAge () {}

Date dahora = new Date();
long MillisToYearsByDiv = 1000l *60l * 60l * 24l * 365l;
long javaOffsetInMillis = 1990l * MillisToYearsByDiv;
long realNowInMillis = dahora.getTime() + javaOffsetInMillis;
long realBirthDayInMillis = this.getFechaNac().getTime() + javaOffsetInMillis;
long ageInMillis = realNowInMillis - realBirthDayInMillis;

return ageInMillis / MillisToYearsByDiv;

สิ่งสำคัญที่สุดคือการทำงานกับจำนวนที่ยาวนานเมื่อคูณและหาร และแน่นอนว่าออฟเซ็ตที่ Java ใช้กับแคลคูลัสของวันที่

:)


2

เนื่องจากคำถามถูกติดแท็กด้วย Scala

import scala.concurrent.duration._
val diff = (System.currentTimeMillis() - oldDate.getTime).milliseconds
val diffSeconds = diff.toSeconds
val diffMinutes = diff.toMinutes
val diffHours = diff.toHours
val diffDays = diff.toDays

2

หลังจากที่ได้อ่านคำตอบอื่น ๆ ทั้งหมดแล้วเพื่อรักษาประเภทวันที่ของ Java 7 ไว้ แต่จะแม่นยำยิ่งขึ้น / เป็นมาตรฐานด้วยแนวทางที่แตกต่างของ Java 8

public static long daysBetweenDates(Date d1, Date d2) {
    Instant instant1 = d1.toInstant();
    Instant instant2 = d2.toInstant();
    long diff = ChronoUnit.DAYS.between(instant1, instant2);
    return diff;
}

1

ลองนี้:

int epoch = (int) (new java.text.SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse("01/01/1970  00:00:00").getTime() / 1000);

คุณสามารถแก้ไขสตริงใน parse () method param

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.