วิธีการสร้างวัตถุ Java Date เที่ยงคืนวันนี้และเที่ยงคืนพรุ่งนี้


178

ในรหัสของฉันฉันต้องการค้นหาทุกสิ่งที่เกิดขึ้นวันนี้ ดังนั้นฉันต้องเปรียบเทียบกับวันที่ตั้งแต่วันนี้เวลา 00:00 น. (เที่ยงคืนของเช้านี้) ถึง 12:00 น. (เที่ยงคืนคืนนี้)

ฉันรู้ว่า ...

Date today = new Date(); 

... ทำให้ฉันตอนนี้ และ ...

Date beginning = new Date(0);

... ทำให้ฉันไม่มีเวลาเลยในวันที่ 1 มกราคม 1970 แต่วิธีง่ายๆในการทำให้เวลาเป็นศูนย์ในวันนี้และเวลาใดจะเป็นศูนย์ในวันพรุ่งนี้

UPDATE; ฉันทำสิ่งนี้ แต่แน่นอนว่ามีวิธีที่ง่ายกว่า

Calendar calStart = new GregorianCalendar();
calStart.setTime(new Date());
calStart.set(Calendar.HOUR_OF_DAY, 0);
calStart.set(Calendar.MINUTE, 0);
calStart.set(Calendar.SECOND, 0);
calStart.set(Calendar.MILLISECOND, 0);
Date midnightYesterday = calStart.getTime();

Calendar calEnd = new GregorianCalendar();
calEnd.setTime(new Date());
calEnd.set(Calendar.DAY_OF_YEAR, calEnd.get(Calendar.DAY_OF_YEAR)+1);
calEnd.set(Calendar.HOUR_OF_DAY, 0);
calEnd.set(Calendar.MINUTE, 0);
calEnd.set(Calendar.SECOND, 0);
calEnd.set(Calendar.MILLISECOND, 0);
Date midnightTonight = calEnd.getTime();

3
ในความเห็นของฉัน Joda Time นั้นง่ายกว่าดูที่ท้ายคำตอบของฉัน หากคุณต้องการใช้ java.util.Date/Calendar คุณต้องทำเช่นนี้ไม่มีวิธีที่ง่ายกว่านี้
timaschew

RE: timaschew แสดงความคิดเห็นเพื่อใช้ Joda-Time รู้ว่าโครงการ Joda-Time อยู่ในโหมดบำรุงรักษาและให้คำแนะนำการย้ายข้อมูลไปยังคลาส java.time
Basil Bourque

1
FYI, ลำบากชะมัดเก่าชั้นเรียนวันที่เวลาเช่นjava.util.Date, java.util.Calendarและjava.text.SimpleDateFormatตอนนี้มรดกแทนที่โดยjava.timeชั้นเรียนที่สร้างขึ้นใน Java 8 และต่อมา ดูการสอนโดยออราเคิล
Basil Bourque

2
มันไม่ค่อยจะเห็นคำตอบที่มีข้อบกพร่องมากมายสำหรับคำถามนี้ ฉันแนะนำคำตอบโดย Basil Bourqueมันถูกต้องและมีความรู้
Ole VV

คำตอบ:


344

java.util.Calendar

// today    
Calendar date = new GregorianCalendar();
// reset hour, minutes, seconds and millis
date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);

// next day
date.add(Calendar.DAY_OF_MONTH, 1);

JDK 8 - java.time.LocalTime และ java.time.LocalDate

LocalTime midnight = LocalTime.MIDNIGHT;
LocalDate today = LocalDate.now(ZoneId.of("Europe/Berlin"));
LocalDateTime todayMidnight = LocalDateTime.of(today, midnight);
LocalDateTime tomorrowMidnight = todayMidnight.plusDays(1);

Joda เวลา

หากคุณใช้ JDK <8 ฉันขอแนะนำJoda Timeเนื่องจาก API นั้นดีมาก:

DateTime date = new DateTime().toDateMidnight().toDateTime();
DateTime tomorrow = date.plusDays(1);

ตั้งแต่เวอร์ชั่น 2.3 ของ Joda Time DateMidnightนั้นเลิกเพื่อใช้นี้

DateTime today = new DateTime().withTimeAtStartOfDay();
DateTime tomorrow = today.plusDays(1).withTimeAtStartOfDay();

ผ่านเขตเวลาหากคุณไม่ต้องการเขตเวลาเริ่มต้นปัจจุบันของ JVM

DateTimeZone timeZone = DateTimeZone.forID("America/Montreal");
DateTime today = new DateTime(timeZone).withTimeAtStartOfDay(); // Pass time zone to constructor.

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

3
ตั้งแต่ JodaTime 2.3 toDateMidnightเลิกใช้แล้ว ดูรายละเอียดคำตอบนี้ได้ที่: stackoverflow.com/a/19048833/363573
Stephan

เพิ่มโซลูชันสำหรับ JDK 8
timaschew

1
@timaschew ในขณะที่ถูกต้องโดยทั่วไปฉันแนะนำให้ทำ java.time โดยใช้ค่าวันที่และเวลา ( ZonedDateTime) ตามที่คุณทำในส่วน Joda-Time Local…ประเภทไม่มีข้อมูลโซนเวลา - นั่นคือจุดประสงค์ของพวกเขาทั้งไม่มีการสูญเสีย / ละเว้นการชดเชยและเวลารายละเอียดโซนทั้งหมด โดยเฉพาะอย่างยิ่งเมื่อคำถามพูดถึงการใช้ค่าเหล่านี้เพื่อการเปรียบเทียบ (อาจเป็นแบบสอบถามฐานข้อมูลหรือไม่) ค่าวันเวลาส่วนที่กำหนดมีแนวโน้มว่าจะมีประโยชน์มากกว่า
Basil Bourque

1
@Amalgovinus ตรวจสอบให้แน่ใจว่าได้ตั้ง Calendar.HOUR_OF_DAY ไม่ใช่ Calendar.HOUR
Oswald

43

เพื่อความครบถ้วนสมบูรณ์ถ้าคุณกำลังใช้Java 8คุณยังสามารถใช้truncatedToวิธีการของInstantระดับที่จะได้รับในเวลาเที่ยงคืนUTC

Instant.now().truncatedTo(ChronoUnit.DAYS);

ตามที่เขียนไว้ใน Javadoc

ตัวอย่างเช่นการตัดทอนด้วยหน่วย MINUTES จะปัดเศษเป็นนาทีที่ใกล้ที่สุดโดยตั้งค่าวินาทีและนาโนวินาทีเป็นศูนย์

หวังว่ามันจะช่วย


1
ขอบคุณสำหรับคำใบ้ รับเที่ยงคืนในเขตเวลาที่กำหนดกลายเป็นอีกต่อไป:Date.from(date.toInstant().atZone(ZoneId.systemDefault()).truncatedTo(ChronoUnit.DAYS).toInstant())
Vadzim


33

วิธีที่ง่ายที่สุดในการค้นหาเที่ยงคืน:

Long time = new Date().getTime();
Date date = new Date(time - time % (24 * 60 * 60 * 1000));

วันถัดไป

Date date = new Date(date.getTime() + 24 * 60 * 60 * 1000);

ฉันเรียกใช้รหัสนั้นและได้รับ: เที่ยงคืน: พ.ย. 01 19:00:00 CDT 2012
เดฟ

3
หากคุณทำอะไรเช่น System.out.print (วันที่) ระบบจะแปลงอินสแตนซ์วันที่เป็นเขตเวลาของระบบ (CDT) 19.00 น. ใน CDT คือเที่ยงคืนของ GMT หากคุณต้องการเที่ยงคืนในเขตเวลาที่เลือกคุณจะต้องเพิ่มออฟเซ็ตของเขตเวลานี้โดยคำนึงถึง DST
Andrei Volgin

@ Bouncner มันคือ มี 'เวลาเที่ยงคืน' ที่แตกต่างกันมากมายบนโลกโดยไม่คำนึงถึงวิธีการที่คุณใช้ แต่มีเที่ยงคืน Java เดียวเท่านั้น
Andrei Volgin

2
@Andrei Volgin ไม่ทราบว่ามี "java เที่ยงคืน" ;) สิ่งที่ฉันอยากจะบอกว่าวิธีการแก้ปัญหานี้ฉันไม่ได้ช่วยผู้สร้างหัวข้อจริงๆ โซลูชันปฏิทินหลีกเลี่ยงการคำนวณที่สองที่น่าเกลียดและดูแลเขตเวลา (และโดยเฉพาะอย่างยิ่งการประหยัดเวลากลางวัน ฯลฯ ) เมื่อใช้อย่างถูกต้อง ฉันไม่เห็นในโซลูชันของคุณ
Bouncner

สวัสดี @AndreiVolgin ฉันมี Date date = new Date (เวลา + TimeZone.getDefault (). getRawOffset () - เวลา% (24 * 60 * 60 * 1000));
jrey

28

จำไว้Dateว่าไม่ได้ใช้เพื่อแสดงวันที่ (!) ในการแสดงวันที่คุณต้องการปฏิทิน นี้:

Calendar c = new GregorianCalendar();

จะสร้างCalendarอินสแตนซ์ที่แสดงวันที่ปัจจุบันในเขตเวลาปัจจุบันของคุณ ตอนนี้สิ่งที่คุณต้องการคือการตัดช่องด้านล่างวัน (ชั่วโมงนาทีวินาทีและมิลลิวินาที) 0ทุกโดยการตั้งค่าให้ ตอนนี้คุณมีเวลาเที่ยงคืนในวันนี้

ตอนนี้รับเที่ยงคืนในวันถัดไปคุณต้องเพิ่มหนึ่งวัน:

c.add(Calendar.DAY_OF_MONTH, 1);

โปรดทราบว่าการเพิ่ม86400วินาทีหรือ 24 ชั่วโมงไม่ถูกต้องเนื่องจากเวลาฤดูร้อนที่อาจเกิดขึ้นในระหว่างนี้

UPDATE: อย่างไรก็ตามวิธีที่ฉันโปรดปรานในการจัดการกับปัญหานี้คือการใช้คลาสDateUtilsจากCommons Lang :

Date start = DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH))
Date end = DateUtils.addDays(start, 1);

มันใช้Calendarเบื้องหลัง ...


15
ขอบคุณสำหรับความช่วยเหลือ "Date ไม่ได้ใช้เพื่อแสดงวันที่" - เราจะเป็นคนที่คลั่งไคล้ที่ยอดเยี่ยมใช่มั้ย ;)

@RobertHume เพื่อให้ยุติธรรมวันที่ได้รับรอบตั้งแต่รุ่นแรกของ Java สิ่งต่าง ๆ ส่วนใหญ่ในยุคนั้น ... น้อยกว่าความคิดที่สมบูรณ์แบบ โดยเฉพาะอย่างยิ่งตั้งแต่ Java เป็นหนึ่งในคนกลุ่มแรก ๆ ที่ลองทำสิ่งต่าง ๆ ที่มันพยายามทำและยังห่างไกลจากมาตรฐานที่ตกลงกันไว้สำหรับวิธีการทำ
คดีของกองทุนโมนิกา

14

วิธีการเหล่านี้จะช่วยคุณ -

public static Date getStartOfDay(Date date) {
     Calendar calendar = Calendar.getInstance();
     calendar.setTime(date);
     calendar.set(Calendar.HOUR_OF_DAY, 0);
     calendar.set(Calendar.MINUTE, 0);
     calendar.set(Calendar.SECOND, 0);
     calendar.set(Calendar.MILLISECOND, 0);
     return calendar.getTime();
 }

และ

public static Date getEndOfDay(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.set(Calendar.HOUR_OF_DAY, 23);
    calendar.set(Calendar.MINUTE, 59);
    calendar.set(Calendar.SECOND, 59);
    calendar.set(Calendar.MILLISECOND, 999);
    return calendar.getTime();
}

9

ตั้งแต่ JodaTime 2.3 เป็นต้นไป toDateMidnight()ไป

จาก อัพเกรดจาก 2.2 เป็น 2.3

    ค่าเสื่อมราคาตั้งแต่ 2.2
    ----------------------
    - DateMidnight [# 41]
     คลาสนี้มีข้อบกพร่องในแนวคิด
     เวลาเที่ยงคืนไม่เกิดขึ้นในบางเขตเวลา
     นี่เป็นผลมาจากเวลาออมแสงตั้งแต่ 00:00 น. ถึง 01:00 น
     DateMidnight เป็นหลัก DateTime ที่มีเวลาล็อคถึงเที่ยงคืน
     แนวคิดดังกล่าวโดยทั่วไปมักจะเป็นแนวคิดที่น่าสงสารที่จะใช้ LocalDate
     แทนที่ DateMidnight ด้วย LocalDate
     หรือแทนที่ด้วย DateTime อาจใช้เมธอด withTimeAtStartOfDay ()

นี่คือตัวอย่างโค้ดที่ไม่มีtoDateMidnight()เมธอด

รหัส

DateTime todayAtMidnight = new DateTime().withTimeAtStartOfDay();
System.out.println(todayAtMidnight.toString("yyyy-MM-dd HH:mm:ss"));

ผลลัพธ์ ( อาจแตกต่างกันไปขึ้นอยู่กับเขตเวลาท้องถิ่นของคุณ )

2013-09-28 00:00:00

2
คำตอบที่ยอดเยี่ยม ฉันจะเพิ่มการส่งDateTimeZoneตัวอย่างไปยังตัวDateTimeสร้างนั้นเพื่อเน้นความสำคัญของการระบุเขตเวลาแทนที่จะตั้งใจโดยไม่ได้ตั้งใจขึ้นอยู่กับค่าเริ่มต้น:DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
Basil Bourque

9

คำตอบอื่น ๆ ที่ถูกต้องโดยเฉพาะอย่างยิ่งคำตอบ java.time โดย arganzheng ดังที่บางคนกล่าวถึงคุณควรหลีกเลี่ยงคลาส java.util.Date/.Calendar เก่าเนื่องจากคลาสเหล่านี้ได้รับการออกแบบไม่ดีสับสนและลำบาก พวกเขาถูกแทนที่ด้วยคลาส java.time

ผมขอเพิ่มบันทึกเกี่ยวกับกลยุทธ์ทั่วจัดการเที่ยงคืนและช่วงเวลา

ครึ่งเปิด

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

การแก้ไขปัญหาหนึ่งคือการกำหนดจุดสิ้นสุดของวัน เป็นนาทีสุดท้ายของวัน23:59:59.999( มิลลิวินาที ) หรือไม่ บางทีในคลาส java.util.Date (จาก Java ตัวเก่าที่สุด, ลำบาก - หลีกเลี่ยงคลาสนี้!) และในไลบรารีJoda-Time ที่ประสบความสำเร็จอย่างสูง แต่ในซอฟต์แวร์อื่น ๆ เช่นฐานข้อมูลเช่น Postgres ช่วงเวลาสุดท้ายจะเป็น23:59:59.999999( ไมโครวินาที ) แต่ในซอฟต์แวร์อื่นเช่นjava.time framework (สร้างขึ้นใน Java 8 และใหม่กว่า, สืบทอดมาจาก Joda-Time) และในฐานข้อมูลบางอย่างเช่นฐานข้อมูลH2 , วินาทีสุดท้ายอาจเป็น23:59.59.999999999( นาโนวินาที ) แทนที่จะแยกผมคิดในแง่ของช่วงเวลาแรกเท่านั้นไม่ใช่ช่วงเวลาสุดท้าย

ใน Half-Open วันทำงานตั้งแต่วินาทีแรกของหนึ่งวันและขึ้นไป แต่ไม่รวมช่วงเวลาแรกของวันถัดไป ดังนั้นแทนที่จะคิดแบบนี้

…จากวันนี้เวลา 00:00 น. (เที่ยงคืนของเช้านี้) ถึง 12:00 น. (เที่ยงคืนคืนนี้)

…คิดแบบนี้…

ตั้งแต่วินาทีแรกของวันนี้จนถึง แต่ไม่รวมช่วงเวลาแรกของวันพรุ่งนี้:
(> = 00:00:00.0วันนี้และ < 00:00:00.0วันพรุ่งนี้)

ในการทำงานของฐานข้อมูลวิธีนี้หมายถึงการไม่ใช้ตัวBETWEENดำเนินการใน SQL

เริ่มวันใหม่

นอกจากนี้ช่วงเวลาแรกของวันนั้นไม่ใช่เวลาของวัน00:00:00.0เสมอไป เวลาออมแสง (DST)ในบางโซนเวลาและความผิดปกติอื่น ๆ อาจหมายถึงการเริ่มต้นวันใหม่

ดังนั้นให้java.timeLocalDate::atStartOfDay( ZoneId )เรียนทำผลงานของการกำหนดจุดเริ่มต้นของวันที่มีการเรียกร้องให้ ดังนั้นเราต้องอ้อมผ่านLocalDateและกลับไปZonedDateTimeอย่างที่คุณเห็นในโค้ดตัวอย่างนี้

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );
ZonedDateTime todayStart = now.toLocalDate().atStartOfDay( zoneId );
ZonedDateTime tomorrowStart = todayStart.plusDays( 1 );

ZoneIdหมายเหตุการผ่านไปของจำเป็น หากละเว้นเขตเวลาเริ่มต้นปัจจุบันของ JVM ของคุณจะถูกนำไปใช้โดยปริยาย ดีกว่าที่จะชัดเจน

เขตเวลาเป็นสิ่งสำคัญสำหรับการทำงานตามวันเวลา คำถามและคำตอบอื่น ๆ อาจมีข้อบกพร่องเนื่องจากไม่มีการจัดการกับโซนเวลา

แปลง

หากคุณต้องใช้ java.util.Date หรือ .Calendar ให้ค้นหาวิธีการแปลงใหม่ที่เพิ่มในคลาสเก่าเหล่านั้น

java.util.Date utilDate = java.util.Date.from( todayStart.toInstant() );
java.util.GregorianCalendar gregCal = java.util.GregorianCalendar.from( todayStart );

ช่วงเวลา

โดยวิธีการถ้าคุณทำงานมากกับช่วงเวลาลองดูที่:

  • Duration
  • Period
  • Interval
    พบIntervalคลาสในโครงการThreeTen-Extraซึ่งเป็นส่วนขยายของเฟรมเวิร์ก java.time โครงการนี้เป็นพื้นฐานที่พิสูจน์ได้สำหรับการเพิ่มเติมในอนาคตไปยัง java.time
    Interval todayMontreal = Interval.of( todayStart.toInstant() , tomorrowStart.toInstant() );

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

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

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

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

คุณสามารถแลกเปลี่ยนวัตถุjava.timeโดยตรงกับฐานข้อมูลของคุณ ใช้ไดรเวอร์ JDBC ที่สอดคล้องกับJDBC 4.2หรือใหม่กว่า ไม่จำเป็นต้องใช้สตริงไม่จำเป็นต้องมีjava.sql.*คลาส

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

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

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


6

java.time

หากคุณใช้ Java 8 และใหม่กว่าคุณสามารถลองแพ็คเกจ java.time ( บทช่วยสอน ):

LocalDate tomorrow = LocalDate.now().plusDays(1);
Date endDate = Date.from(tomorrow.atStartOfDay(ZoneId.systemDefault()).toInstant());

2
คำตอบที่ดี. ฉันขอแนะนำให้ระบุโซนเวลาที่ต้องการ / ที่คาดไว้ โซนเวลาเริ่มต้นปัจจุบันของ JVM สามารถแตกต่างกันไปตามการตั้งค่าระบบปฏิบัติการการเปลี่ยนคอมพิวเตอร์หรือแอพใด ๆ ในเธรดของ JVM ใด ๆ ที่เปลี่ยนค่าเริ่มต้นได้ตลอดเวลาในระหว่างรันไทม์
Basil Bourque

4

สิ่งนี้ดูเหมือนจะเป็นตัวเลือก:

DateFormat justDay = new SimpleDateFormat("yyyyMMdd");
Date thisMorningMidnight = justDay.parse(justDay.format(new Date()));

เพื่อเพิ่มวันเข้าด้วยกัน

Date tomorrow = new Date(thisMorningMidnight.getTime() + 24 * 60 * 60 * 1000);

หรือ

Calendar c = Calendar.getInstance();
c.setTime(thisMorningMidnight);
c.add(Calendar.DATE, 1);
Date tomorrowFromCalendar = c.getTime();

ฉันมีลางสังหรณ์หลังเป็นที่ต้องการในกรณีที่มีสิ่งแปลกประหลาดเช่นการประหยัดเวลากลางวันทำให้เพิ่ม 24 ชั่วโมงไม่เพียงพอ (ดูhttps://stackoverflow.com/a/4336131/32453และคำตอบอื่น ๆ )


ฉันมีวันที่และเวลาของวันแสดงเป็นระยะเวลานานในฐานข้อมูล sqlite ของฉัน ฉันต้องใช้เวลานานในการเริ่มต้นของวันถัดไป ฉันยังคงสามารถใช้วัตถุวันที่ที่มีความยาวมากกว่าวิธีการ SimpleDateFormat ที่คุณใช้ด้านบนได้หรือไม่?
AJW

1
ตราบใดที่มันเป็นมิลลิวินาทีที่ถูกต้องคุณสามารถผ่านมันเป็นตัวสร้าง: docs.oracle.com/javase/7/docs/api/java/util/ ......
rogerdpack

1

ฉันทำสิ่งนี้แตกต่างจากคนอื่นที่นี่ ฉันใหม่กับ Java ดังนั้นบางทีโซลูชันของฉันอาจไม่ดี

Date now = new Date();
Date midnightToday = new Date(now.getYear(), now.getMonth(), now.getDate());

ฉันยังไม่แน่ใจว่ายังใช้งานได้ แต่อย่างใดฉันขอขอบคุณข้อเสนอแนะเกี่ยวกับการแก้ปัญหา

ฉันสับสนโดยข้อความข้างต้นที่คุณสามารถคำนวณในวันพรุ่งนี้โดยโทร:

c.add(Calendar.DAY_OF_MONTH, 1);

หากคุณเพิ่ม 1 ลงในวันที่ของเดือนและเป็นวันที่ 31 คุณจะไม่ได้รับวันที่ 32 ของเดือนใช่หรือไม่

ทำไมเวลา / วันที่ไม่ได้อ้างอิง UTC ใน Java? ฉันคิดว่าเขตเวลาควรมีความจำเป็นเมื่อใช้กับ i / o เท่านั้น แต่ควรใช้ภายในใน UTC เสมอ อย่างไรก็ตามคลาสดูเหมือนจะมีข้อมูลเขตเวลาซึ่งไม่เพียง แต่สิ้นเปลือง แต่มีแนวโน้มที่จะเกิดข้อผิดพลาดในการเขียนโค้ด


2
สวัสดีมิทช์ ฉันคิดว่าโซลูชันของคุณใช้งานได้ แต่ดูเหมือนว่าตัวสร้าง Date นั้นเลิกใช้แล้ว Java folks เลิกใช้วิธีการที่เกี่ยวข้องกับวันที่เดิมมาได้สักพักแล้วแทนที่ด้วยวิธีการที่เกี่ยวข้องกับปฏิทินที่ใหม่กว่า ส่วนตัวฉันไม่เห็นว่ามันเป็นการปรับปรุง แต่มันขมวดคิ้วในการใช้วิธีการเลิก ขอบคุณ!

น่าเศร้าเกี่ยวกับการคัดค้าน ฉันรู้สึกดีกว่าที่จะระบุปีเดือนและวันที่มากกว่าการล้างชั่วโมงนาทีวินาทีและมิลลิวินาที การล้างสิ่งเหล่านี้ขึ้นอยู่กับมิลลิวินาทีซึ่งเป็นสิ่งที่ดีที่สุดของคลาส Date ในขณะที่โซลูชันของฉันไม่ โซลูชันของฉันสั้นลงและชัดเจนขึ้น การใหม่กับ Java ทำให้ฉันรู้สึกขอบคุณจริง ๆ ว่า C ++ นั้นสะอาดง่ายและมีประสิทธิภาพเพียงใดเมื่อใช้วันที่และเวลา
มิทช์

@Mitch จากประสบการณ์ของฉันภาษาล่าสุดที่คุณกำลังเรียนรู้มักจะถูกมองว่าซับซ้อนที่สุด
ArtOfWarfare

FYI: คลาสวันที่และเวลาอันเก่าแก่ที่น่ากลัวเหล่านี้กลายเป็นมรดกแทนที่ด้วยคลาส java.time ที่ทันสมัย
Basil Bourque


0

วิธีที่ง่ายที่สุดกับ JodaTime

DateMidnight date = DateMidnight.now();


2
ไม่คลาสและวิธีการที่เกี่ยวข้องกับ "เที่ยงคืน" ใน Joda-Time ถูกคัดค้านทั้งหมด พวกเขาขึ้นอยู่กับแนวคิดที่มีข้อบกพร่อง ช่วงเวลาแรกของวันนั้นไม่เสมอ00:00:00.000ไป ใช้withTimeAtStartOfDayวิธีการใหม่แทน อัปเดตเป็น Joda-Time เวอร์ชั่นปัจจุบันและอ่านบันทึกประจำรุ่น ตัวอย่าง:DateTime today = DateTime.now( DateTimeZone.forID( "America/Montreal" ) ).withTimeAtStartOfDay();
Basil Bourque

0

เนื่องจากหนึ่งวันคือ24 * 60 * 60 * 1000ms เที่ยงคืนของวันนี้จึงสามารถคำนวณเป็น ...

long now = System.currentTimeMillis();
long delta = now % 24 * 60 * 60 * 1000;
long midnight = now - delta;
Date midnightDate = new Date(midnight);`

1
รหัสนี้ใช้กับ UTC เท่านั้นและไม่มีเขตเวลาอื่นและละเว้นความผิดปกติเช่นเวลาออมแสง นอกจากนี้โซลูชันวันเวลาย้อนกลับที่คุณทำเองนั้นไม่ฉลาดเพราะนี่เป็นหัวข้อที่ยุ่งยากอย่างน่าประหลาดใจ ใช้คลาส java.time ที่ยอดเยี่ยมแทน
Basil Bourque

0

ค่อนข้างเป็นคำตอบก่อนหน้านี้ แต่ไม่มีใครพูดถึงพารามิเตอร์ AM_PM:

    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.HOUR, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    cal.set(Calendar.AM_PM, Calendar.AM);

1
ลำบากCalendarชั้นถูกแทนที่ปีที่ผ่านมาโดยjava.timeZonedDateTimeเรียนโดยเฉพาะ
Basil Bourque

0
Date now= new Date();
// Today midnight
Date todayMidnight = new Date(endTime.getTime() -endTime.getTime()%DateUtils.MILLIS_PER_DAY);

// tomorrow midnight
Date tomorrowMidnight = new Date(endTime.getTime() -endTime.getTime()%DateUtils.MILLIS_PER_DAY + DateUtils.MILLIS_PER_DAY);

ใช้งานได้กับ UTC เท่านั้นและไม่สามารถระบุเขตเวลาได้ นอกจากนี้ที่น่ากลัวระดับถูกแทนที่โดยปีที่ผ่านมาDate java.time.Instantหลีกเลี่ยงการใช้Dateในปัจจุบัน
Basil Bourque

0

ใช้ apache ทั่วไป ..

//For midnight today 
Date today = new Date(); 
DateUtils.truncate(today, Calendar.DATE);

//For midnight tomorrow   
Date tomorrow = DateUtils.addDays(today, 1); 
DateUtils.truncate(tomorrow, Calendar.DATE);

FYI, ลำบากชะมัดเก่าชั้นเรียนวันที่เวลาเช่นjava.util.Date, java.util.Calendarและjava.text.SimpleDateFormatตอนนี้มรดกแทนที่โดยjava.timeชั้นเรียนที่สร้างขึ้นใน Java 8 และต่อมา ดูการสอนโดยออราเคิล
Basil Bourque

@BasilBourque เห็นด้วยกับ Java 8 แต่ถ้า OP ใช้ Java 7 ฉันก็ยังเดาว่ามันจะใช้ได้
joe4java

ฟังก์ชันjava.timeเกือบทั้งหมดพร้อมใช้งานสำหรับ Java 6 & 7 ในโครงการThreeTen-Backportด้วย API ที่เหมือนกัน ดัดแปลงเพิ่มเติมสำหรับ Android <26 ในโครงการThreeTenABP ดังนั้นไม่จำเป็นต้องใช้คลาสวันที่เก่าแก่ที่น่าสังเวชอีกเลย
Basil Bourque

-1

ฉันรู้ว่านี่เป็นโพสต์เก่ามาก ฉันคิดว่าจะแบ่งปันความรู้ของฉันที่นี่!

สำหรับวันมิดไนท์วันนี้ด้วยโซนเวลาที่แน่นอนคุณสามารถใช้ต่อไปนี้

public static Date getCurrentDateWithMidnightTS(){

    return new Date(System.currentTimeMillis() - (System.currentTimeMillis()%(1000*60*60*24)) - (1000*60 * 330));
}

โดยที่ (1000*60 * 330)จะถูกลบออกเช่นที่เกี่ยวข้องกับเขตเวลาจริงเช่นเขตเวลาของอินเดียเช่นโกลกาตาแตกต่างจาก +5: 30hrs จากที่เกิดขึ้นจริง ดังนั้นการลบด้วยการแปลงเป็นมิลลิวินาที

ดังนั้นเปลี่ยนหมายเลขที่ถูกย่อท้ายตามที่คุณต้องการ ฉันกำลังสร้างผลิตภัณฑ์เช่นใช้ในอินเดียเท่านั้นดังนั้นใช้เวลาประทับเฉพาะ


1
ทำไมคุณถึงแนะนำสิ่งนี้แทนคำตอบที่ยอมรับ? การหมุนค่าวันที่และเวลาของคุณมีความเสี่ยงโดยทั่วไป โดยเฉพาะอย่างยิ่งรหัสนี้มีการกำหนดรหัสอย่างหนักให้กับออฟเซ็ตปัจจุบันของเขตเวลาเดียวตลอดไป ไม่มีการบันทึกเวลาตามฤดูกาลหรือความผิดปกติอื่น ๆ ฉันเห็นข้อเสียเท่านั้นที่ไม่มีมูลค่าเพิ่ม
Basil Bourque

@Basil แน่นอนฉันยอมรับคำตอบและใช่ฉันกล่าวถึงที่นั่นเพื่อหาค่าฮาร์ดโค้ด สิ่งนี้มีประโยชน์เฉพาะในกรณีที่คุณทำงานในเขตเวลาที่เฉพาะเจาะจง
Rajeev

-1
Date todayMidnightUTC = java.sql.Date.valueOf(LocalDate.now());
Date tomorrowMidnightUTC = java.sql.Date.valueOf(LocalDate.now().plusDays(1));
Date anyMidnightLocal = java.sql.Date.valueOf(LocalDate.from(dateTime.toInstant().atZone(ZoneId.systemDefault())));

แต่ระวังว่าเสมอพ่นjava.sql.Date.toInstant()UnsupportedOperationException

ผ่านLocalDate ถึง java.util.Date และในทางกลับกันการแปลงที่ง่ายที่สุด?


ไม่ใช่คำตอบที่ดี คุณกำลังผสมการใช้ java.time ที่ทันสมัยกับคลาสดั้งเดิมที่พวกเขาแทนที่ และโดยเฉพาะคุณใช้คลาสวันที่ java.sql ที่ควรใช้สำหรับการแลกเปลี่ยนข้อมูลกับฐานข้อมูลที่มีไดรเวอร์ที่ยังไม่ได้รับการอัพเดตเพื่อจัดการกับคลาส java.time โดยตรงไม่ควรใช้สำหรับตรรกะทางธุรกิจ อีกปัญหาหนึ่งคือคุณไม่สนใจประเด็นสำคัญของเขตเวลา
Basil Bourque

@BasilBourque ขอบคุณสำหรับคำวิจารณ์ การใช้คลาสดั้งเดิมหนึ่งคลาสที่ไม่ได้ทำเครื่องหมายว่าเลิกใช้เพื่อรับอินสแตนซ์ของคลาสดั้งเดิมอีกอันนั้นค่อนข้างปลอดภัย ปัญหาเขตเวลามีความสำคัญมากกว่า ฉันตัดสินใจที่จะติดกับคาร์โด้ของคำตอบหลังจากทั้งหมด
Vadzim

-1

วิธีการแบบเก่า ..

private static Date getDateWithMidnight(){
    long dateInMillis = new Date().getTime();
    return new Date(dateInMillis - dateInMillis%(1000*60*60*24) - TimeZone.getDefault().getOffset(dateInMillis));
}

คลาสที่ลำบากนั้นถูกแทนที่เมื่อหลายปีก่อนโดยคลาสjava.time.Instant Dateไม่จำเป็นต้องใช้ที่เคย
Basil Bourque

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