Setel waktu ke 00:00:00

121

Saya mengalami masalah saat menyetel ulang jam di Java. Untuk tanggal tertentu saya ingin menyetel jam ke 00:00:00.

Ini kode saya:

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

Masalahnya adalah bahwa kadang-kadang waktunya 12:00:00dan kadang-kadang begitu 00:00:00dan ketika saya menanyakan database untuk entitas yang disimpan di 07.02.2013 00:00:00dan waktu entitas aktual, yang disimpan, adalah12:00:00 kueri gagal.

saya tahu itu 12:00:00 == 00:00:00 !

Saya menggunakan AppEngine. Apakah ini bug appengine, masalah atau masalah lain? Atau apakah itu tergantung pada hal lain?

Adelin
sumber
Mungkinkah ini ada hubungannya dengan lokal yang berbeda atau apakah ini terjadi dari PC yang sama sepanjang waktu?
LostBoy
itu terjadi ketika saya menerapkan di appengine.
Adelin
Banyak solusi lain untuk memotong waktu: stackoverflow.com/a/1908955/2646526
heenenee
FYI, kelas waktu kencan lama yang merepotkan seperti java.util.Date,java.util.Calendar , dan java.text.SimpleDateFormatsekarang warisan , digantikan oleh java.time kelas dibangun ke Jawa 8 & Java 9. Lihat Tutorial oleh Oracle .
Basil Bourque
1
Saya menggunakan calendar.set(Calendar.HOUR_OF_DAY, 0);, untuk tujuan saya, ini bekerja dengan baik.
hariprasad

Jawaban:

209

Gunakan konstanta lain sebagai pengganti Calendar.HOUR, gunakan Calendar.HOUR_OF_DAY.

calendar.set(Calendar.HOUR_OF_DAY, 0);

Calendar.HOUR menggunakan 0-11 (untuk digunakan dengan AM / PM), dan Calendar.HOUR_OF_DAY menggunakan 0-23.

Mengutip Javadocs:

JAM public int static final

Nomor field untuk mendapatkan dan mengatur yang menunjukkan jam pagi atau sore hari. HOUR digunakan untuk format 12-jam (0-11). Siang dan tengah malam diwakili oleh 0, bukan 12. Misalnya, pada 10: 04: 15.250 JAM adalah 10.

dan

HOUR_OF_DAY public int static final

Nomor bidang untuk dapatkan dan set yang menunjukkan jam hari ini. HOUR_OF_DAY digunakan untuk format 24 jam. Misalnya, pada pukul 10: 04: 15.250, HOUR_OF_DAY adalah pukul 22.

Pengujian ("sekarang" saat ini sekitar 14:55 pada 23 Juli 2013 Waktu Musim Panas Pasifik):

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

Keluaran:

$ javac Main.java
$ java Main
2013-07-23 12:00:00
2013-07-23 00:00:00
rgettman
sumber
3
@JarrodRoberson Tetapi menggunakan Calendar.HOURtidak akan menyetel PM ke AM, meninggalkannya sebagai jam 12 siang.
rgettman
Bisakah Anda membantu saya dalam membuat LocalDate dengan jam, menit, dan detik? Saya tahu salah satu pilihan adalah mengikuti DateTime.
Woody
11
Siapa pun yang membuat bidang HOUR dan HOUR_OF_DAY seharusnya dicambuk dan diberi jatah.
AndroidDev
1
@AndroidDev siapa pun yang menemukan am / pm berhak mendapatkan hal yang sama ... Ini juga berlaku untuk standar non-metrik
Dediqated
1
FYI, merepotkan tua kelas tanggal-waktu seperti java.util.Date,java.util.Calendar , dan java.text.SimpleDateFormatsekarang warisan , digantikan oleh java.time kelas dibangun ke Jawa 8 & Java 9. Lihat Tutorial oleh Oracle .
Basil Bourque
29

java.time

Menggunakan java.timekerangka kerja bawaan Java 8 dan yang lebih baru. Lihat Tutorial .

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

Jika Anda tidak membutuhkan waktu (jam, menit, detik, dll.) Pertimbangkan untuk menggunakan LocalDatekelas.

LocalDate.now(); # 2015-11-19
Przemek
sumber
Ini seharusnya merupakan jawaban baru yang diterima karena Java 1.8 telah dirilis sejak pertanyaan ini pertama kali diajukan.
matt forsythe
LocalDateTimeadalah kelas yang salah untuk digunakan untuk ini. Ini tidak dapat mewakili momen karena tidak memiliki konsep zona waktu atau offset-dari-UTC. Menelepon LocalDateTime.nowhampir tidak pernah masuk akal. Gunakan ZonedDateTimesebagai gantinya. Jika tidak, Anda mengabaikan masalah zona waktu yang krusial. Untuk satu hal, beberapa tanggal di beberapa zona tidak dimulai pada 00:00!
Basil Bourque
12

Berikut adalah beberapa fungsi utilitas yang saya gunakan untuk melakukan hal ini.

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

sumber
6

Satu lagi JAVA 8 cara:

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

Tetapi jauh lebih berguna untuk mengedit tanggal yang sudah ada.

thorinkor
sumber
1
LocalDateTimetidak dapat mewakili momen, karena tidak memiliki konsep zona waktu atau offset-dari-UTC. Menelepon LocalDateTime.nowhampir tidak pernah masuk akal. Anda harus menggunakan ZonedDateTimesebagai gantinya.
Basil Bourque
3

Anda sebaiknya menyetel zona waktu ke komponen DateFormat seperti ini:

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

Kemudian Anda bisa mendapatkan waktu "00:00:00" dengan meneruskan 0 milidetik ke formatter:

String time = dateFormat.format(0);

atau Anda dapat membuat objek Tanggal:

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

atau Anda dapat memiliki lebih banyak kemungkinan menggunakan komponen Kalender tetapi Anda juga harus mengatur zona waktu sebagai GMT ke contoh kalender:

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());
Dmitriy Smerchinskiy
sumber
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

Anda menggunakan kelas tanggal-waktu lama yang mengerikan yang telah diganti bertahun-tahun yang lalu oleh kelas java.time modern yang ditentukan di JSR 310.

DateInstant

A java.util.Datemewakili momen dalam UTC. Penggantinya adalah Instant. Panggil metode konversi baru yang ditambahkan ke kelas lama.

Instant instant = myJavaUtilDate.toInstant() ;

Zona waktu

Tentukan zona waktu yang Anda inginkan untuk waktu-of-hari Anda yang baru.

Tentukan nama zona waktu yang tepat dalam format Continent/Region, seperti America/Montreal, Africa/Casablanca, atau Pacific/Auckland. Jangan pernah menggunakan singkatan 2-4 huruf seperti ESTatau ISTkarena itu bukan zona waktu yang sebenarnya, tidak terstandarisasi, dan bahkan tidak unik (!).

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

ZonedDateTime

Terapkan ZoneIdke Instantuntuk mendapatkan a ZonedDateTime. Momen yang sama, titik yang sama di garis waktu, tetapi waktu jam dinding yang berbeda.

ZonedDateTime zdt = instant.atZone( z ) ;

Mengubah waktu hari

Anda meminta untuk mengubah waktu hari. Terapkan a LocalTimeuntuk mengubah semua bagian waktu hari: jam, menit, detik, pecahan detik. Yang baru ZonedDateTimedibuat instance-nya, dengan nilai-nilai berdasarkan aslinya. The java.time kelas menggunakan ini objek abadi pola untuk menyediakan benang-keselamatan .

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

Momen pertama hari ini

Tapi Anda meminta secara khusus untuk 00:00. Jadi rupanya Anda menginginkan momen pertama hari itu. Hati-hati: beberapa hari di beberapa zona tidak dimulai pada 00:00:00. Mereka mungkin mulai pada waktu lain seperti 01:00:00 karena anomali seperti Daylight Saving Time (DST).

Biarkan java.time menentukan momen pertama. Ekstrak bagian khusus tanggal. Kemudian lewati zona waktu untuk mendapatkan momen pertama.

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

Sesuaikan dengan UTC

Jika Anda perlu kembali ke UTC, ekstrak file Instant.

Instant instant = zdtFirstMomentOfDay.toInstant() ;

InstantDate

Jika Anda membutuhkan java.util.Dateuntuk beroperasi dengan kode lama yang belum diperbarui ke java.time , ubah.

java.util.Date d = java.util.Date.from( instant ) ;
Basil Bourque
sumber
1

Melakukan ini bisa lebih mudah (Di Java 8)

LocalTime.ofNanoOfDay(0)
meszias
sumber
Terima kasih, saya bekerja dengan barang lain 2 tahun terakhir, dan Java 6/7 sebelumnya. Saya telah kembali ke Java sekarang (setelah bekerja dengan beberapa hal di Groovy) dan menyukai perbedaan Java 8.
meszias
1

Kita dapat mengatur bagian waktu java.util.Date ke 00:00:00 Dengan menggunakan kelas LocalDate dari 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
Atishay
sumber
1

Jika Anda membutuhkan format 00:00:00 dalam string, Anda harus menggunakan SimpleDateFormat seperti di bawah ini. Menggunakan "H", bukan "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
Ngô Ngọc Quang
sumber
0

Cara lain untuk melakukannya adalah dengan menggunakan DateFormat tanpa detik:

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;
}
MMascarin
sumber
0

Anda dapat melakukan ini dengan yang berikut:

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

Karena Java8 menambahkan fungsi Tanggal baru, kita dapat melakukan ini dengan mudah.


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

Chao Jiang
sumber
LocalDateTimetidak dapat mewakili momen, karena tidak memiliki konsep zona waktu atau offset-dari-UTC. Menelepon LocalDateTime.nowhampir tidak pernah masuk akal. Anda harus menggunakan ZonedDateTimesebagai gantinya.
Basil Bourque