Establecer la hora en 00:00:00

121

Tengo un problema al restablecer las horas en Java. Para una fecha determinada, quiero establecer el horario en 00:00:00.

Este es mi codigo:

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

El problema es que a veces el tiempo es 12:00:00y otras veces es 00:00:00y cuando consulto la base de datos para una entidad en la que se guardó 07.02.2013 00:00:00y el tiempo real de la entidad, que está almacenado, 12:00:00falla la consulta.

Yo se eso 12:00:00 == 00:00:00!

Estoy usando AppEngine. ¿Se trata de un error, un problema del motor o algún otro problema? ¿O depende de otra cosa?

Adelin
fuente
¿Podría esto tener algo que ver con diferentes configuraciones regionales o sucede desde la misma PC todo el tiempo?
LostBoy
sucede cuando implemento en appengine.
Adelin
Muchas otras soluciones para reducir el tiempo: stackoverflow.com/a/1908955/2646526
heenenee
Para su información, las problemáticas clases antiguas de fecha y hora como java.util.Date, java.util.Calendary java.text.SimpleDateFormatahora son heredadas , suplantadas por las clases java.time integradas en Java 8 y Java 9. Consulte el tutorial de Oracle .
Basil Bourque
1
Usé calendar.set(Calendar.HOUR_OF_DAY, 0);, para mi propósito, funciona bien.
hariprasad

Respuestas:

209

Use otra constante en lugar de Calendar.HOURuse Calendar.HOUR_OF_DAY.

calendar.set(Calendar.HOUR_OF_DAY, 0);

Calendar.HOURusa 0-11 (para usar con AM / PM) y Calendar.HOUR_OF_DAYusa 0-23.

Para citar los Javadocs:

público estático final int HORA

Número de campo para get y set que indica la hora de la mañana o de la tarde. HOUR se utiliza para el reloj de 12 horas (0-11). El mediodía y la medianoche están representados por 0, no por 12. Por ejemplo, a las 10: 04: 15.250 PM la HORA es 10.

y

public static final int HOUR_OF_DAY

Número de campo para obtener y configurar que indica la hora del día. HOUR_OF_DAY se utiliza para el reloj de 24 horas. Por ejemplo, a las 10: 04: 15.250 p. M., El HOUR_OF_DAY es 22.

Pruebas ("ahora" es actualmente a las 14:55 del 23 de julio de 2013, hora de verano del Pacífico):

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

Salida:

$ javac Main.java
$ java Main
2013-07-23 12:00:00
2013-07-23 00:00:00
rgettman
fuente
3
@JarrodRoberson Pero el uso Calendar.HOURno establecería PM en AM, dejándolo como 12:00 del mediodía.
rgettman
¿Puede ayudarme a construir un LocalDate con horas, minutos y segundos? Sé que una opción es seguir DateTime.
Woody
11
Quien haya creado el campo HOUR y HOUR_OF_DAY debería haber sido azotado y puesto en raciones.
AndroidDev
1
@AndroidDev quien inventó am / pm merece lo mismo ... Esto también se
aplica a los
1
Para su información, las problemáticas clases antiguas de fecha y hora como java.util.Date, java.util.Calendary java.text.SimpleDateFormatahora son heredadas , suplantadas por las clases java.time integradas en Java 8 y Java 9. Consulte el tutorial de Oracle .
Basil Bourque
29

java.time

Usando el java.timemarco integrado en Java 8 y posterior. Ver 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

Si no necesita la hora del día (horas, minutos, segundos, etc.), considere usar la LocalDateclase.

LocalDate.now(); # 2015-11-19
Przemek
fuente
Esta debería ser la nueva respuesta aceptada desde que se lanzó Java 1.8 desde que se hizo esta pregunta por primera vez.
Matt forsythe
LocalDateTimees exactamente la clase incorrecta para usar para esto. No puede representar un momento ya que carece de cualquier concepto de zona horaria o desplazamiento de UTC. Llamar LocalDateTime.nowcasi nunca tiene sentido. Úselo en su ZonedDateTimelugar. De lo contrario, está ignorando los problemas cruciales de la zona horaria. Por un lado, ¡algunas fechas en algunas zonas no comienzan a las 00:00!
Basil Bourque
12

Aquí hay un par de funciones de utilidad que utilizo para hacer esto.

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

fuente
6

Una forma más de JAVA 8:

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

Pero es mucho más útil editar la fecha que ya existe.

Thorinkor
fuente
1
LocalDateTimeno puede representar un momento, ya que carece de cualquier concepto de zona horaria o desplazamiento de UTC. Llamar LocalDateTime.nowcasi nunca tiene sentido. Deberías estar usando en su ZonedDateTimelugar.
Basil Bourque
3

Será mejor que establezca principalmente la zona horaria en el componente DateFormat de esta manera:

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

Luego, puede obtener el tiempo "00:00:00" pasando 0 milisegundos al formateador:

String time = dateFormat.format(0);

o puede crear un objeto Date:

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

o puede tener más posibilidades usando el componente Calendario, pero también debe establecer la zona horaria como GMT para la instancia 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());
Dmitriy Smerchinskiy
fuente
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

Está utilizando terribles clases de fecha y hora antiguas que fueron suplantadas hace años por las clases modernas de java.time definidas en JSR 310.

DateInstant

A java.util.Daterepresenta un momento en UTC. Su reemplazo es Instant. Llame a los nuevos métodos de conversión agregados a las clases antiguas.

Instant instant = myJavaUtilDate.toInstant() ;

Zona horaria

Especifique la zona horaria en la que desea que tenga sentido su nueva hora del día.

Especificar un nombre de zona horaria correcta en el formato de Continent/Region, por ejemplo America/Montreal, Africa/Casablancao Pacific/Auckland. Nunca use el 2-4 abreviatura de letras tales como ESTo IST, ya que son no verdaderas zonas de tiempo, no estandarizados, y ni siquiera único (!).

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

ZonedDateTime

Aplique el ZoneIdal Instantpara obtener un ZonedDateTime. Mismo momento, mismo punto en la línea de tiempo, pero diferente hora del reloj de pared.

ZonedDateTime zdt = instant.atZone( z ) ;

Cambiar la hora del día

Pediste cambiar la hora del día. Aplique a LocalTimepara cambiar todas las partes de la hora del día: hora, minuto, segundo, fracción de segundo. Se ZonedDateTimecrea una instancia de un nuevo , con valores basados ​​en el original. Las clases java.time utilizan este patrón de objetos inmutables para proporcionar seguridad para subprocesos .

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

Primer momento del día

Pero pediste específicamente 00:00. Entonces, aparentemente, quieres el primer momento del día. Atención: algunos días en algunas zonas no comienzan a las 00:00:00. Es posible que comiencen a otra hora, como la 01:00:00, debido a anomalías como el horario de verano (DST).

Deje que java.time determine el primer momento. Extrae la parte de solo fecha. Luego pase la zona horaria para obtener el primer momento.

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

Ajustar a UTC

Si necesita volver a UTC, extraiga un archivo Instant.

Instant instant = zdtFirstMomentOfDay.toInstant() ;

InstantDate

Si necesita java.util.Dateinteroperar con un código antiguo que aún no se ha actualizado a java.time , convierta.

java.util.Date d = java.util.Date.from( instant ) ;
Albahaca Bourque
fuente
1

Hacer esto podría ser más fácil (en Java 8)

LocalTime.ofNanoOfDay(0)
meszias
fuente
Gracias, trabajé con otras cosas los últimos 2 años y Java 6/7 antes. He vuelto a Java ahora (después de trabajar con algunas cosas en Groovy) y me gustan las diferencias de Java 8.
meszias
1

Podemos establecer la parte de tiempo java.util.Date en 00:00:00 usando la clase LocalDate de 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
fuente
1

Si necesita el formato 00:00:00 en una cadena, debe usar SimpleDateFormat como se muestra a continuación. Usando "H" en lugar de "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
fuente
0

Otra forma de hacer esto sería usar un DateFormat sin segundos:

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;
}
MMascarina
fuente
0

Puede hacer esto con lo siguiente:

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

Como Java8 agrega nuevas funciones de fecha, podemos hacerlo fácilmente.


    // 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
fuente
LocalDateTimeno puede representar un momento, ya que carece de cualquier concepto de zona horaria o desplazamiento de UTC. Llamar LocalDateTime.nowcasi nunca tiene sentido. Deberías estar usando en su ZonedDateTimelugar.
Basil Bourque