Đặt thời gian thành 00:00:00


121

Tôi gặp sự cố khi đặt lại giờ trong Java. Đối với một ngày nhất định, tôi muốn đặt giờ thành 00:00:00.

Đây là mã của tôi:

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

Vấn đề là đôi khi thời gian là 12:00:00và đôi khi nó là 00:00:00và khi tôi truy vấn cơ sở dữ liệu cho một thực thể đã được lưu trên 07.02.2013 00:00:00và thời gian thực thể thực thể, được lưu trữ, 12:00:00truy vấn không thành công.

Tôi biết điều đó 12:00:00 == 00:00:00!

Tôi đang sử dụng AppEngine. Đây là lỗi appengine, sự cố hay một số vấn đề khác? Hay nó phụ thuộc vào thứ gì khác?


Điều này có thể liên quan đến các ngôn ngữ khác nhau hoặc điều này luôn xảy ra với cùng một PC?
LostBoy

nó xảy ra khi tôi triển khai trên appengine.
Adelin

Rất nhiều giải pháp khác để cắt giảm thời gian: stackoverflow.com/a/1908955/2646526
heenenee 02/02

FYI, các lớp date-time cũ rắc rối như java.util.Date, java.util.Calendarjava.text.SimpleDateFormatbây giờ là kế thừa , được thay thế bởi các lớp java.time được tích hợp trong Java 8 & Java 9. Xem Hướng dẫn của Oracle .
Basil Bourque

1
Tôi đã sử dụng calendar.set(Calendar.HOUR_OF_DAY, 0);, cho mục đích của tôi, nó hoạt động tốt.
hariprasad

Câu trả lời:


209

Sử dụng hằng số khác thay vì Calendar.HOUR, sử dụng Calendar.HOUR_OF_DAY.

calendar.set(Calendar.HOUR_OF_DAY, 0);

Calendar.HOURsử dụng 0-11 (để sử dụng với AM / PM) và Calendar.HOUR_OF_DAYsử dụng 0-23.

Để trích dẫn Javadocs:

công khai tĩnh cuối cùng int HOUR

Số trường cho nhận và đặt cho biết giờ của buổi sáng hoặc buổi chiều. HOUR được sử dụng cho đồng hồ 12 giờ (0 - 11). Buổi trưa và nửa đêm được biểu thị bằng 0, không phải bằng 12. Ví dụ: lúc 10: 04: 15.250 CH thì GIỜ là 10.

public static final int HOUR_OF_DAY

Số trường cho get và set cho biết giờ trong ngày. HOUR_OF_DAY được sử dụng cho đồng hồ 24 giờ. Ví dụ: lúc 10: 04: 15.250 chiều, HOUR_OF_DAY là 22.

Kiểm tra ("bây giờ" hiện là 14:55 ngày 23 tháng 7 năm 2013 Giờ ban ngày Thái Bình Dương):

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()));
    }
}

Đầu ra:

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

3
@JarrodRoberson Nhưng việc sử dụng Calendar.HOURsẽ không đặt PM thành AM, để nó là 12:00 trưa.
rgettman

Bạn có thể vui lòng giúp tôi trong việc tạo LocalDate với giờ, phút và giây được không? Tôi biết một tùy chọn là theo dõi DateTime.
Woody

11
Ai đã tạo ra trường HOUR và HOUR_OF_DAY lẽ ra phải được đánh dấu và đưa vào khẩu phần ăn.
AndroidDev

1
@AndroidDev bất cứ ai phát minh ra sáng / chiều đều xứng đáng như vậy ... Điều này cũng áp dụng cho các tiêu chuẩn phi số liệu
Dediqated

1
FYI, các lớp date-time cũ rắc rối như java.util.Date, java.util.Calendarjava.text.SimpleDateFormatbây giờ là kế thừa , được thay thế bởi các lớp java.time được tích hợp trong Java 8 & Java 9. Xem Hướng dẫn của Oracle .
Basil Bourque

29

java.time

Sử dụng java.timekhung được tích hợp trong Java 8 trở lên. Xem Hướng dẫn .

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

Nếu bạn không cần thời gian trong ngày (giờ, phút, giây, v.v.), hãy cân nhắc sử dụng LocalDatelớp học.

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

Đây phải là câu trả lời mới được chấp nhận vì Java 1.8 đã được phát hành kể từ khi câu hỏi này được hỏi lần đầu tiên.
matt forsythe

LocalDateTimechính xác là lớp sai để sử dụng cho việc này. Nó không thể đại diện cho một thời điểm vì nó thiếu bất kỳ khái niệm nào về múi giờ hoặc chênh lệch từ UTC. Gọi LocalDateTime.nowhầu như không bao giờ có ý nghĩa. Sử dụng ZonedDateTimethay thế. Nếu không, bạn đang bỏ qua các vấn đề quan trọng về múi giờ. Có điều, một số ngày ở một số khu vực không bắt đầu lúc 00:00!
Basil Bourque

12

Dưới đây là một số chức năng tiện ích tôi sử dụng để thực hiện việc này.

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

Thêm một JAVA 8 cách:

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

Nhưng sẽ hữu ích hơn nhiều nếu chỉnh sửa ngày đã tồn tại.


1
LocalDateTimekhông thể đại diện cho một thời điểm, vì nó thiếu bất kỳ khái niệm nào về múi giờ hoặc độ lệch từ UTC. Gọi LocalDateTime.nowhầu như không bao giờ có ý nghĩa. Bạn nên sử dụng ZonedDateTimethay thế.
Basil Bourque

3

Bạn nên chủ yếu đặt múi giờ cho thành phần DateFormat như thế này:

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

Sau đó, bạn có thể nhận được thời gian "00:00:00" bằng cách chuyển 0 mili giây để định dạng:

String time = dateFormat.format(0);

hoặc bạn có thể tạo đối tượng Ngày:

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

hoặc bạn có thể có nhiều khả năng hơn bằng cách sử dụng thành phần Lịch nhưng bạn cũng nên đặt múi giờ là GMT cho phiên bản lịch:

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

Bạn đang sử dụng các lớp date-time cũ khủng khiếp đã được thay thế nhiều năm trước bởi các lớp java.time hiện đại được định nghĩa trong JSR 310.

DateInstant

Một java.util.Dateđại diện cho một thời điểm trong UTC. Thay thế của nó là Instant. Gọi các phương thức chuyển đổi mới được thêm vào các lớp cũ.

Instant instant = myJavaUtilDate.toInstant() ;

Múi giờ

Chỉ định múi giờ mà bạn muốn giờ mới trong ngày của mình có ý nghĩa.

Chỉ định một tên múi giờ thích hợp trong các định dạng của Continent/Region, chẳng hạn như America/Montreal, Africa/Casablancahoặc Pacific/Auckland. Không bao giờ sử dụng từ viết tắt 2-4 chữ cái, chẳng hạn như ESThoặc ISTvì chúng không phải là múi giờ thực, không được tiêu chuẩn hóa và thậm chí không phải là duy nhất (!).

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

ZonedDateTime

Áp dụng ZoneIdcho Instantđể có được a ZonedDateTime. Cùng một thời điểm, cùng một điểm trên dòng thời gian, nhưng thời gian trên đồng hồ treo tường khác nhau.

ZonedDateTime zdt = instant.atZone( z ) ;

Thay đổi thời gian trong ngày

Bạn đã yêu cầu thay đổi thời gian trong ngày. Áp dụng a LocalTimeđể thay đổi tất cả các phần thời gian trong ngày: giờ, phút, giây, giây phân số. Một mới ZonedDateTimeđược khởi tạo, với các giá trị dựa trên bản gốc. Các lớp java.time sử dụng mẫu đối tượng bất biến này để cung cấp sự an toàn cho luồng .

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

Khoảnh khắc đầu tiên trong ngày

Nhưng bạn đã yêu cầu cụ thể cho 00:00. Vì vậy, dường như bạn muốn khoảnh khắc đầu tiên trong ngày. Lưu ý: một số ngày ở một số khu vực không bắt đầu lúc 00:00:00. Chúng có thể bắt đầu vào một thời điểm khác, chẳng hạn như 01:00:00 do các điểm bất thường như Giờ tiết kiệm ánh sáng ban ngày (DST).

Hãy để java.time xác định thời điểm đầu tiên. Trích xuất phần chỉ ngày. Sau đó vượt qua múi giờ để có được khoảnh khắc đầu tiên.

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

Điều chỉnh theo UTC

Nếu bạn cần quay lại UTC, hãy trích xuất một Instant.

Instant instant = zdtFirstMomentOfDay.toInstant() ;

InstantDate

Nếu bạn cần một java.util.Dateđể tương tác với mã cũ chưa được cập nhật lên java.time , hãy chuyển đổi.

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

1

Làm điều này có thể dễ dàng hơn (Trong Java 8)

LocalTime.ofNanoOfDay(0)

Cảm ơn bạn, tôi đã làm việc với những thứ khác trong 2 năm trước và Java 6/7 trước đó. Bây giờ tôi đã quay lại Java (sau khi làm việc với một số thứ trên Groovy) và thích sự khác biệt của Java 8.
meszias

1

Chúng ta có thể đặt phần thời gian của java.util.Date thành 00:00:00 bằng cách sử dụng lớp LocalDate của 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

Nếu bạn cần định dạng 00:00:00 trong chuỗi, bạn nên sử dụng SimpleDateFormat như bên dưới. Sử dụng "H" thay vì "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

Một cách khác để làm điều này sẽ là sử dụng DateFormat mà không có bất kỳ giây nào:

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

Bạn có thể làm điều này với những điều sau:

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

0

Khi Java8 thêm các hàm Date mới, chúng ta có thể thực hiện điều này một cách dễ dàng.


    // 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


LocalDateTimekhông thể đại diện cho một thời điểm, vì nó thiếu bất kỳ khái niệm nào về múi giờ hoặc độ lệch từ UTC. Gọi LocalDateTime.nowhầu như không bao giờ có ý nghĩa. Bạn nên sử dụng ZonedDateTimethay thế.
Basil Bourque
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.