ตั้งเวลาเป็น 00:00:00 น


121

ฉันมีปัญหาในการรีเซ็ตชั่วโมงใน Java สำหรับวันที่กำหนดฉันต้องการตั้งเวลาเป็น 00:00:00 น.

นี่คือรหัสของฉัน:

/**
     * Resets milliseconds, seconds, minutes and hours from the provided date
     *
     * @param date
     * @return
     */
    public static Date trim(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR, 0);

        return calendar.getTime();
    }

ปัญหาคือบางครั้งเวลาเป็น12:00:00และบางครั้งก็เป็นเช่นนั้น00:00:00และเมื่อฉันสอบถามฐานข้อมูลสำหรับเอนทิตีที่ถูกบันทึกไว้07.02.2013 00:00:00และเวลาของเอนทิตีจริงที่ถูกจัดเก็บคือ12:00:00แบบสอบถามล้มเหลว

รู้แล้ว12:00:00 == 00:00:00!

ฉันใช้ AppEngine นี่เป็นข้อบกพร่องของ appengine ปัญหาหรือปัญหาอื่น ๆ หรือไม่? หรือไม่ขึ้นอยู่กับอย่างอื่น?


สิ่งนี้อาจเกี่ยวข้องกับสถานที่ต่างๆหรือสิ่งนี้เกิดขึ้นจากพีซีเครื่องเดียวกันตลอดเวลาหรือไม่?
LostBoy

มันเกิดขึ้นเมื่อฉันปรับใช้กับ appengine
Adelin

วิธีแก้ปัญหาอื่น ๆ อีกมากมายสำหรับการตัดเวลา: stackoverflow.com/a/1908955/2646526
heenenee

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

1
ฉันใช้calendar.set(Calendar.HOUR_OF_DAY, 0);เพื่อวัตถุประสงค์ของฉันมันได้ผลดี
hariprasad

คำตอบ:


209

ใช้อย่างต่อเนื่องอื่นแทนการใช้Calendar.HOURCalendar.HOUR_OF_DAY

calendar.set(Calendar.HOUR_OF_DAY, 0);

Calendar.HOURใช้ 0-11 (สำหรับใช้กับ AM / PM) และCalendar.HOUR_OF_DAYใช้ 0-23

หากต้องการอ้างอิง Javadocs:

สาธารณะ int สุดท้ายคงที่ชั่วโมง

หมายเลขฟิลด์สำหรับรับและตั้งค่าระบุชั่วโมงของตอนเช้าหรือตอนบ่าย HOUR ใช้สำหรับนาฬิกา 12 ชั่วโมง (0 - 11) เที่ยงและเที่ยงคืนแทนด้วย 0 ไม่ใช่ 12 เช่นเวลา 10: 04: 15.250 น. HOUR คือ 10

และ

สาธารณะคง int สุดท้าย HOUR_OF_DAY

หมายเลขฟิลด์สำหรับรับและตั้งค่าระบุชั่วโมงของวัน HOUR_OF_DAY ใช้สำหรับนาฬิกา 24 ชั่วโมง เช่นเวลา 10: 04: 15.250 น. HOUR_OF_DAY คือ 22

การทดสอบ ("ตอนนี้" คือเวลา 14:55 น. ของวันที่ 23 กรกฎาคม 2013 เวลาออมแสงแปซิฟิก):

public class Main
{
   static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args)
    {
        Calendar now = Calendar.getInstance();
        now.set(Calendar.HOUR, 0);
        now.set(Calendar.MINUTE, 0);
        now.set(Calendar.SECOND, 0);
        System.out.println(sdf.format(now.getTime()));
        now.set(Calendar.HOUR_OF_DAY, 0);
        System.out.println(sdf.format(now.getTime()));
    }
}

เอาท์พุท:

$ javac Main.java
$ java Main
2013-07-23 12:00:00
2013-07-23 00:00:00

3
@JarrodRoberson แต่การใช้งานCalendar.HOURจะไม่ตั้งค่า PM เป็น AM ปล่อยให้เป็น 12.00 น.
rgettman

คุณช่วยฉันสร้าง LocalDate แบบชั่วโมงนาทีและวินาทีได้ไหม ฉันรู้ว่าทางเลือกหนึ่งคือติดตาม DateTime
Woody

11
ใครก็ตามที่สร้างฟิลด์ HOUR และ HOUR_OF_DAY ควรถูกเฆี่ยนและปันส่วน
AndroidDev

1
@AndroidDev ใครก็ตามที่คิดค้น am / pm สมควรได้รับเช่นเดียวกัน ... สิ่งนี้ก็เป็นไปตามมาตรฐานที่ไม่ใช่เมตริก
Dediqated

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

29

java.time

ใช้java.timeเฟรมเวิร์กที่สร้างใน Java 8 และใหม่กว่า ดูการสอน

import java.time.LocalTime;
import java.time.LocalDateTime;

LocalDateTime now = LocalDateTime.now(); # 2015-11-19T19:42:19.224
# start of a day
now.with(LocalTime.MIN); # 2015-11-19T00:00
now.with(LocalTime.MIDNIGHT); # 2015-11-19T00:00

หากคุณไม่ต้องการเวลาของวัน (ส่วนชั่วโมงนาทีวินาที ฯลฯ ) ให้พิจารณาใช้LocalDateคลาส

LocalDate.now(); # 2015-11-19

นี่ควรเป็นคำตอบใหม่ที่ได้รับการยอมรับเนื่องจาก Java 1.8 ได้รับการเผยแพร่ตั้งแต่คำถามนี้ถูกถามครั้งแรก
Matt forsythe

LocalDateTimeเป็นคลาสที่ไม่ถูกต้องที่จะใช้สำหรับสิ่งนี้ ไม่สามารถแสดงช่วงเวลาได้เนื่องจากไม่มีแนวคิดเกี่ยวกับเขตเวลาหรือ offset-from-UTC โทรหาLocalDateTime.nowแทบไม่เข้าท่า ใช้ZonedDateTimeแทน มิฉะนั้นคุณจะเพิกเฉยต่อปัญหาเขตเวลาที่สำคัญ ประการหนึ่งคือบางวันในบางโซนจะไม่เริ่มเวลา 00:00 น.!
Basil Bourque

12

นี่คือฟังก์ชั่นยูทิลิตี้สองสามอย่างที่ฉันใช้ทำสิ่งนี้

/**
 * sets all the time related fields to ZERO!
 *
 * @param date
 *
 * @return Date with hours, minutes, seconds and ms set to ZERO!
 */
public static Date zeroTime( final Date date )
{
    return DateTimeUtil.setTime( date, 0, 0, 0, 0 );
}

/**
 * Set the time of the given Date
 *
 * @param date
 * @param hourOfDay
 * @param minute
 * @param second
 * @param ms
 *
 * @return new instance of java.util.Date with the time set
 */
public static Date setTime( final Date date, final int hourOfDay, final int minute, final int second, final int ms )
{
    final GregorianCalendar gc = new GregorianCalendar();
    gc.setTime( date );
    gc.set( Calendar.HOUR_OF_DAY, hourOfDay );
    gc.set( Calendar.MINUTE, minute );
    gc.set( Calendar.SECOND, second );
    gc.set( Calendar.MILLISECOND, ms );
    return gc.getTime();
}

6

อีกหนึ่งวิธี JAVA 8:

LocalDateTime localDateTime = LocalDateTime.now().truncatedTo(ChronoUnit.HOURS);

แต่การแก้ไขวันที่ที่มีอยู่แล้วมีประโยชน์มากกว่านั้นมาก


1
LocalDateTimeไม่สามารถแสดงช่วงเวลาได้เนื่องจากไม่มีแนวคิดเกี่ยวกับเขตเวลาหรือ offset-from-UTC โทรหาLocalDateTime.nowแทบไม่เข้าท่า คุณควรใช้ZonedDateTimeแทน
Basil Bourque

3

คุณควรตั้งค่าโซนเวลาเป็นหลักเป็นส่วนประกอบ DateFormat ดังนี้:

DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));

จากนั้นคุณจะได้รับเวลา "00:00:00" โดยผ่าน 0 มิลลิวินาทีในการฟอร์แมต:

String time = dateFormat.format(0);

หรือคุณสามารถสร้างวัตถุวันที่:

Date date = new Date(0); // also pass milliseconds
String time = dateFormat.foramt(date);

หรือคุณสามารถมีความเป็นไปได้มากขึ้นโดยใช้องค์ประกอบปฏิทิน แต่คุณควรตั้งเขตเวลาเป็น GMT เป็นอินสแตนซ์ปฏิทิน:

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.US);
calendar.set(Calendar.HOUR_OF_DAY, 5);
calendar.set(Calendar.MINUTE, 37);
calendar.set(Calendar.SECOND, 27);

dateFormat.format(calendar.getTime());

2

TL; DR

myJavaUtilDate                                 // The terrible `java.util.Date` class is now legacy. Use *java.time* instead.
.toInstant()                                   // Convert this moment in UTC from the legacy class `Date` to the modern class `Instant`.
.atZone( ZoneId.of( "Africa/Tunis" ) )         // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone).
.toLocalDate()                                 // Extract the date-only portion.
.atStartOfDay( ZoneId.of( "Africa/Tunis" ) )   // Determine the first moment of that date in that zone. The day does *not* always start at 00:00:00.

java.time

คุณกำลังใช้คลาสวันที่ - เวลาเก่าที่แย่มากซึ่งถูกแทนที่เมื่อหลายปีก่อนโดยคลาสjava.timeสมัยใหม่ที่กำหนดไว้ใน JSR 310

DateInstant

java.util.Dateแทนช่วงเวลาใน UTC เราจะต้อง Instantทดแทนของมันคือ เรียกใช้วิธีการแปลงใหม่ที่เพิ่มลงในคลาสเก่า

Instant instant = myJavaUtilDate.toInstant() ;

เขตเวลา

ระบุเขตเวลาที่คุณต้องการให้เวลาใหม่ของวันเหมาะสม

ระบุชื่อโซนเวลาที่เหมาะสมในรูปแบบของContinent/Regionเช่นAmerica/Montreal, หรือAfrica/Casablanca Pacific/Aucklandอย่าใช้ตัวย่อ 2-4 ตัวอักษรเช่นESTหรือISTเนื่องจากไม่ใช่เขตเวลาจริงไม่เป็นมาตรฐานและไม่ซ้ำกัน (!)

ZoneId z = ZoneId.of( "America/Montreal" ) ;

ZonedDateTime

นำZoneIdไปใช้Instantเพื่อรับไฟล์ZonedDateTime. ช่วงเวลาเดียวกันจุดเดียวกันบนไทม์ไลน์ แต่เวลานาฬิกาแขวนต่างกัน

ZonedDateTime zdt = instant.atZone( z ) ;

การเปลี่ยนเวลาของวัน

คุณขอให้เปลี่ยนเวลาของวัน ใช้ a LocalTimeเพื่อเปลี่ยนแปลงส่วนเวลาของวันทั้งหมด: ชั่วโมงนาทีวินาทีเศษส่วนของวินาที ใหม่ZonedDateTimeถูกสร้างอินสแตนซ์โดยมีค่าตามต้นฉบับ java.timeชั้นเรียนนี้ใช้วัตถุที่ไม่เปลี่ยนรูปแบบเพื่อให้ด้ายความปลอดภัย

LocalTime lt = LocalTime.of( 15 , 30 ) ;  // 3:30 PM.
ZonedDateTime zdtAtThreeThirty = zdt.with( lt ) ; 

ช่วงเวลาแรกของวัน

แต่คุณถามเป็นพิเศษสำหรับ 00:00 น. เห็นได้ชัดว่าคุณต้องการช่วงเวลาแรกของวัน ระวัง: บางวันในบางโซนไม่เริ่มเวลา 00:00:00 น. อาจเริ่มในเวลาอื่นเช่น 01:00:00 น. เนื่องจากความผิดปกติเช่นเวลาออมแสง (DST)

ให้java.timeกำหนดช่วงเวลาแรก แยกส่วนวันที่เท่านั้น จากนั้นผ่านเขตเวลาเพื่อรับช่วงเวลาแรก

LocalDate ld = zdt.toLocalDate() ;
ZonedDateTime zdtFirstMomentOfDay = ld.atStartOfDay( z ) ;

ปรับเป็น UTC

หากคุณต้องการกลับไปที่ UTC ให้ดึงInstantไฟล์.

Instant instant = zdtFirstMomentOfDay.toInstant() ;

InstantDate

หากคุณต้องการjava.util.Dateทำงานร่วมกับโค้ดเก่าที่ยังไม่ได้อัปเดตเป็นjava.timeให้แปลง

java.util.Date d = java.util.Date.from( instant ) ;

1

การทำเช่นนี้อาจง่ายขึ้น (ใน Java 8)

LocalTime.ofNanoOfDay(0)

ขอบคุณฉันทำงานกับสิ่งอื่น ๆ เมื่อ 2 ปีที่แล้วและ Java 6/7 ก่อนหน้านั้น ฉันกลับมาที่ Java แล้ว (หลังจากทำงานกับ Groovy ไม่กี่อย่าง) และชอบความแตกต่างของ Java 8
meszias

1

เราสามารถตั้งค่าส่วนเวลาjava.util.Dateเป็น00:00:00โดยใช้คลาส LocalDate ของJava 8 / Joda-datetime api :

Date datewithTime = new Date() ; // ex: Sat Apr 21 01:30:44 IST 2018
LocalDate localDate = LocalDate.fromDateFields(datewithTime);
Date datewithoutTime = localDate.toDate(); // Sat Apr 21 00:00:00 IST 2018

1

หากคุณต้องการรูปแบบ 00:00:00 ในสตริงคุณควรใช้ SimpleDateFormat ดังต่อไปนี้ โดยใช้ "H" แทน "h"

Date today = new Date();
SimpleDateFormat ft = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); 
//not SimpleDateFormat("dd-MM-yyyy hh:mm:ss")
Calendar calendarDM = Calendar.getInstance();
calendarDM.setTime(today);
calendarDM.set(Calendar.HOUR, 0);
calendarDM.set(Calendar.MINUTE, 0);
calendarDM.set(Calendar.SECOND, 0);
System.out.println("Current Date: " + ft.format(calendarDM.getTime()));

//Result is: Current Date: 29-10-2018 00:00:00

0

อีกวิธีในการทำเช่นนี้คือการใช้ DateFormat โดยไม่ต้องวินาทีใด ๆ :

public static Date trim(Date date) {
    DateFormat format = new SimpleDateFormat("dd.MM.yyyy");
    Date trimmed = null;
    try {
        trimmed = format.parse(format.format(date));
    } catch (ParseException e) {} // will never happen
    return trimmed;
}

0

คุณสามารถทำได้ดังต่อไปนี้:

Calendar cal = Calendar.getInstance();
cal.set(year, month, dayOfMonth, 0, 0, 0);
Date date = cal.getTime();

0

เมื่อ Java8 เพิ่มฟังก์ชัน Date ใหม่เราสามารถทำได้อย่างง่ายดาย


    // If you have instant, then:
    Instant instant1 = Instant.now();
    Instant day1 = instant1.truncatedTo(ChronoUnit.DAYS);
    System.out.println(day1); //2019-01-14T00:00:00Z

    // If you have Date, then:
    Date date = new Date();
    Instant instant2 = date.toInstant();
    Instant day2 = instant2.truncatedTo(ChronoUnit.DAYS);
    System.out.println(day2); //2019-01-14T00:00:00Z

    // If you have LocalDateTime, then:
    LocalDateTime dateTime = LocalDateTime.now();
    LocalDateTime day3 = dateTime.truncatedTo(ChronoUnit.DAYS);
    System.out.println(day3); //2019-01-14T00:00
    String format = day3.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    System.out.println(format);//2019-01-14T00:00:00


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