Imposta l'ora su 00:00:00


121

Ho un problema a reimpostare l'orario in Java. Per una determinata data voglio impostare le ore su 00:00:00.

Questo è il mio codice:

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

Il problema è che a volte l'ora è 12:00:00ea volte lo è 00:00:00e quando interrogo il database per un'entità su cui è stata salvata 07.02.2013 00:00:00e l'ora effettiva dell'entità, che è archiviata, 12:00:00la query non riesce.

Lo so 12:00:00 == 00:00:00!

Sto usando AppEngine. È un bug, un problema o un altro problema di Appengine? O dipende da qualcos'altro?


Potrebbe avere qualcosa a che fare con localizzazioni diverse o accade sempre dallo stesso PC?
LostBoy

succede quando eseguo il deployment su appengine.
Adelin

Un sacco di altre soluzioni per tagliare tempo: stackoverflow.com/a/1908955/2646526
heenenee

Cordiali saluti, le vecchie classi data-ora problematiche come java.util.Date, java.util.Calendare java.text.SimpleDateFormatora sono legacy , soppiantate dalle classi java.time incorporate in Java 8 e Java 9. Vedi Tutorial di Oracle .
Basil Bourque

1
Ho usato calendar.set(Calendar.HOUR_OF_DAY, 0);, per il mio scopo, funziona bene.
hariprasad

Risposte:


209

Usa un'altra costante invece di Calendar.HOUR, usa Calendar.HOUR_OF_DAY.

calendar.set(Calendar.HOUR_OF_DAY, 0);

Calendar.HOURutilizza 0-11 (per l'utilizzo con AM / PM) e Calendar.HOUR_OF_DAYutilizza 0-23.

Per citare i Javadoc:

public static final int HOUR

Numero di campo per ottenere e impostare che indica l'ora del mattino o del pomeriggio. HOUR viene utilizzato per l'orologio a 12 ore (0-11). Mezzogiorno e mezzanotte sono rappresentate da 0, non da 12. Ad esempio, alle 10: 04: 15.250 PM l'ORA è 10.

e

public static final int HOUR_OF_DAY

Numero di campo per ottenere e impostare che indica l'ora del giorno. HOUR_OF_DAY viene utilizzato per l'orologio a 24 ore. Ad esempio, alle 10: 04: 15.250 PM, HOUR_OF_DAY è 22.

Test ("ora" è attualmente alle 14:55 circa del 23 luglio 2013 Pacific Daylight Time):

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

Produzione:

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

3
@JarrodRoberson Ma l'utilizzo Calendar.HOURnon imposterebbe PM su AM, lasciandolo a mezzogiorno.
rgettman

Potete aiutarmi a costruire un LocalDate con ore, minuti e secondi? So che un'opzione è seguire DateTime.
Woody

11
Chiunque abbia creato il campo HOUR e HOUR_OF_DAY avrebbe dovuto essere frustato e messo su razioni.
AndroidDev

1
@AndroidDev chiunque abbia inventato am / pm merita lo stesso ... Questo vale anche per gli standard non metrici
Dediqated

1
Cordiali saluti, le vecchie classi data-ora problematiche come java.util.Date, java.util.Calendare java.text.SimpleDateFormatora sono legacy , soppiantate dalle classi java.time incorporate in Java 8 e Java 9. Vedi Tutorial di Oracle .
Basil Bourque

29

java.time

Utilizzando il java.timeframework integrato in Java 8 e versioni successive. Vedi 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

Se non hai bisogno dell'ora del giorno (ore, minuti, secondi ecc.) Considera l'utilizzo della LocalDateclasse.

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

Questa dovrebbe essere la nuova risposta accettata poiché Java 1.8 è stato rilasciato dalla prima domanda.
matt forsythe

LocalDateTimeè esattamente la classe sbagliata da usare per questo. Non può rappresentare un momento in quanto manca di alcun concetto di fuso orario o offset da UTC. Chiamare LocalDateTime.nownon ha quasi mai senso. Usa ZonedDateTimeinvece. Altrimenti ignori i problemi cruciali del fuso orario. Per prima cosa, alcune date in alcune zone non iniziano alle 00:00!
Basil Bourque

12

Qui ci sono un paio di funzioni di utilità che uso per fare proprio questo.

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

Un altro modo JAVA 8:

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

Ma è molto più utile modificare la data già esistente.


1
LocalDateTimenon può rappresentare un momento, in quanto manca il concetto di fuso orario o offset da UTC. Chiamare LocalDateTime.nownon ha quasi mai senso. Dovresti usare ZonedDateTimeinvece.
Basil Bourque

3

È meglio impostare principalmente il fuso orario sul componente DateFormat in questo modo:

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

Quindi puoi ottenere l'ora "00:00:00" passando 0 millisecondi al formattatore:

String time = dateFormat.format(0);

oppure puoi creare un oggetto Data:

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

oppure puoi avere più possibilità utilizzando il componente Calendar, ma dovresti anche impostare il fuso orario come GMT nell'istanza del calendario:

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

Stai usando terribili vecchie classi data-ora che sono state soppiantate anni fa dalle moderne classi java.time definite in JSR 310.

DateInstant

A java.util.Daterappresenta un momento in UTC. La sua sostituzione è Instant. Chiama i nuovi metodi di conversione aggiunti alle vecchie classi.

Instant instant = myJavaUtilDate.toInstant() ;

Fuso orario

Specifica il fuso orario in cui desideri che la nuova ora del giorno abbia un senso.

Specificare un nome proprio fuso orario nel formato Continent/Region, come ad esempio America/Montreal, Africa/Casablancao Pacific/Auckland. Non usare mai il 2-4 lettera sigla come ad esempio ESTo ISTcome sono non fusi orari veri e propri, non standardizzati, e nemmeno unico (!).

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

ZonedDateTime

Applicare il ZoneIda Instantper ottenere un file ZonedDateTime. Stesso momento, stesso punto sulla timeline, ma diverso tempo dell'orologio da parete.

ZonedDateTime zdt = instant.atZone( z ) ;

Modifica dell'ora del giorno

Hai chiesto di cambiare l'ora del giorno. Applicare a LocalTimeper modificare tutte le parti dell'ora del giorno: ora, minuti, secondi, frazioni di secondo. Viene ZonedDateTimeistanziato un nuovo , con valori basati sull'originale. Le classi java.time utilizzano questo modello di oggetti immutabili per fornire la sicurezza del thread .

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

Primo momento della giornata

Ma hai chiesto specificatamente per 00:00. Quindi a quanto pare vuoi il primo momento della giornata. Attenzione: alcuni giorni in alcune zone non iniziano alle 00:00:00. Potrebbero iniziare in un altro momento, ad esempio 01:00:00, a causa di anomalie come l'ora legale (DST).

Lascia che java.time determini il primo momento. Estrai la parte di sola data. Quindi passa il fuso orario per ottenere il primo momento.

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

Regola su UTC

Se devi tornare a UTC, estrai un file Instant.

Instant instant = zdtFirstMomentOfDay.toInstant() ;

InstantDate

Se hai bisogno di un java.util.Dateper interagire con il vecchio codice non ancora aggiornato a java.time , converti.

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

1

Fare questo potrebbe essere più semplice (in Java 8)

LocalTime.ofNanoOfDay(0)

Grazie, ho lavorato con altre cose negli ultimi 2 anni e prima con Java 6/7. Sono tornato a Java ora (dopo aver lavorato con poche cose su Groovy) e mi sono piaciute le differenze di Java 8.
meszias

1

Possiamo impostare la parte temporale di java.util.Date su 00:00:00 utilizzando la classe LocalDate di 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

Se hai bisogno del formato 00:00:00 in stringa, dovresti usare SimpleDateFormat come di seguito. Usare "H" invece di "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

Un altro modo per farlo sarebbe usare un DateFormat senza secondi:

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

Puoi farlo con quanto segue:

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

0

Poiché Java8 aggiunge nuove funzioni di data, possiamo farlo facilmente.


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


LocalDateTimenon può rappresentare un momento, in quanto manca il concetto di fuso orario o offset da UTC. Chiamare LocalDateTime.nownon ha quasi mai senso. Dovresti usare ZonedDateTimeinvece.
Basil Bourque
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.