web-dev-qa-db-fra.com

Informations sur l'heure limite Java Date

J'ai un objet Date Java contenant des informations de date et d'heure. Je veux écrire une méthode qui coupe les informations de temps, tronque les heures-minutes-secondes, de sorte que je n'ai plus que la date.

Exemple d'entrée:

2008-01-01 13:15:00

Production attendue:

2008-01-01 00:00:00

Avez-vous un pourboire? J'ai essayé de faire quelque chose comme ça:

(timestamp / (24 * 60 * 60 * 1000)) * (24 * 60 * 60 * 1000)

mais j'ai rencontré des problèmes avec le fuseau horaire.

97
Marco

La manière recommandée par de manipuler la date/heure consiste à utiliser un Calendar object

Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(dateObject);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long time = cal.getTimeInMillis();
157
cletus

Avez-vous examiné la méthode DateUtils truncate dans Apache Commons Lang?

Date truncatedDate = DateUtils.truncate(new Date(), Calendar.DATE);

va supprimer l'élément de temps.

128
A_M

Avez-vous regardé Joda ? C'est un beaucoup moyen plus facile et plus intuitif de travailler avec les dates et les heures. Par exemple, vous pouvez convertir trivialement entre (par exemple) LocalDateTime et LocalDate objects.

par exemple. (pour illustrer l'API)

LocalDate date = new LocalDateTime(milliseconds).toLocalDate()

De plus, il résout certains problèmes de sécurité des threads avec les formateurs de date/heure et doit être fortement recommandé pour traiter des problèmes de date/heure en Java.

38
Brian Agnew
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
date = cal.getTime();
23
jitter

Juste une mise à jour rapide à la lumière des classes Java.time maintenant intégrées à Java 8 et versions ultérieures.

LocalDateTime a une truncatedTo méthode qui répond efficacement à ce dont vous parlez ici:

LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES)

Cela exprimera l'heure actuelle en minutes seulement:

2015-03-05T11:47

Vous pouvez utiliser n'importe quel ChronoUnit (ou même tout TemporalUnit ) pour exécuter la troncature.

21
Adam Berry

Avec Joda, vous pouvez facilement obtenir la date prévue.

À partir de la version 2.7 (peut-être depuis une version antérieure supérieure à 2.2), comme le note le commentateur, toDateMidnight est devenu obsolète en faveur ou le nom bien nommé withTimeAtStartOfDay(), rendant la

DateTime.now().withTimeAtStartOfDay()

possible.

Bénéficiez d'une API plus agréable.

Avec les anciennes versions, vous pouvez faire

new DateTime(new Date()).toDateMidnight().toDate()
20
h7r

Utilisez DateUtils d’Apache, avec truncate, comme ceci:

DateUtils.truncate(Calendar.getInstance().getTime(), Calendar.DATE);

Pour les horodatages:

timestamp -= timestamp % (24 * 60 * 60 * 1000)
6
Gan Quan

J'ai fait la troncature avec la nouvelle API Java8. J'ai fait face à une chose étrange mais en général c'est tronqué ...

Instant instant = date.toInstant();
instant = instant.truncatedTo(ChronoUnit.DAYS);
date = Date.from(instant);
5
Sergio Kosik

De Java.util.Date JavaDocs:

La classe Date représente un instant précis dans le temps, avec une précision d'une milliseconde

et à partir des JavaDocs Java.sql.Date:

Pour se conformer à la définition de SQL DATE, les valeurs millisecondes encapsulées par une instance Java.sql.Date doivent être «normalisées» en définissant les heures, minutes, secondes et millisecondes sur zéro dans le fuseau horaire auquel l'instance est associée. .

Donc, la meilleure approche consiste à utiliser Java.sql.Date si vous n’avez pas besoin de la partie temps.

Java.util.Date utilDate = new Java.util.Date();
Java.sql.Date sqlDate = new Java.sql.Date(System.currentTimeMillis());

et le résultat est:

Java.util.Date : Thu Apr 26 16:22:53 PST 2012
Java.sql.Date  : 2012-04-26
3
Sunil Manheri

tl; dr

LocalDateTime.parse(                            // Lacking an offset or time zone, parse as a `LocalDateTime`. *Not* a specific moment in time.
    "2008-01-01 13:15:00".replace( " " , "T" )  // Alter input string to comply with ISO 8601 standard format.
)
.toLocalDate()                                  // Extract a date-only value.
.atStartOfDay(                                  // Do not assume the day starts at 00:00:00. Let class determine start-of-day.
    ZoneId.of( "Europe/Paris" )                 // Determining a specific start-of-day requires a time zone.
)                                               // Result is a `ZonedDateTime` object. At this point we have a specific moment in time, a point on the timeline.
.toString()                                     // Generate a String in standard ISO 8601 format, wisely extended to append the name of the time zone in square brackets.

2008-01-01T00: 00 + 01: 00 [Europe/Paris]

Pour générer une chaîne au format souhaité, transmettez un DateTimeFormatter

LocalDateTime.parse(                            // Lacking an offset or time zone, parse as a `LocalDateTime`. *Not* a specific moment in time.
    "2008-01-01 13:15:00".replace( " " , "T" )  // Alter input string to comply with ISO 8601 standard format.
)
.toLocalDate()                                  // Extract a date-only value.
.atStartOfDay(                                  // Do not assume the day starts at 00:00:00. Let class determine start-of-day.
    ZoneId.of( "Europe/Paris" )                 // Determining a specific start-of-day requires a time zone.
)                                               // Result is a `ZonedDateTime` object. At this point we have a specific moment in time, a point on the timeline.
.format(                                        // Generate a String representing the object’s value.
    DateTimeFormatter.ISO_LOCAL_DATE_TIME       // Built-in predefined formatter close to what you want. 
)
.replace( "T" , " " )                           // Replace the standard’s use of a 'T' in the middle with your desired SPACE character.

2008-01-01 00:00:00

Détails

Les autres réponses sont correctes, mais utilisez les anciennes classes date-heure désormais obsolètes du framework Java.time.

Java.time

Le framework Java.time est intégré à Java 8 et versions ultérieures. Une grande partie de la fonctionnalité Java.time est rétroportée vers Java 6 et 7 ( ThreeTen-Backport ) et ensuite adaptée à Android ( ThreeTenABP ).

Commencez par modifier la chaîne d'entrée pour qu'elle soit conforme à la version canonique du format ISO 8601. Les formats standard ISO 8601 sont utilisés par défaut dans les classes Java.time pour analyser/générer des chaînes représentant des valeurs date-heure. Nous devons remplacer cet espace au milieu par un T.

String input = "2008-01-01 13:15:00".replace( " " , "T" );  // → 2008-01-01T13:15:00

Nous pouvons maintenant l’analyser comme un LocalDateTime , où «Local» ne désigne aucune localité spécifique. Il manque dans l'entrée des informations relatives à { décalage par rapport à l'heure UTC ou au fuseau horaire.

LocalDateTime ldt = LocalDateTime.parse( input );

ldt.toString ()… 2008-01-01T13: 15: 00

Si vous ne vous souciez pas de l'heure ni du fuseau horaire, convertissez-le en LocalDate .

LocalDate ld = ldt.toLocalDate();

ld.toString ()… 2008-01-01

Premier moment du jour

Si vous souhaitez plutôt que l'heure du jour soit définie au premier moment de la journée, utilisez une classe ZonedDateTime , puis convertissez-la en objet LocalDate pour appeler sa méthode atStartOfDay . Sachez que le premier moment n'est peut-être pas l'heure 00:00:00 à cause de l'heure d'été ou d'autres anomalies.

Le fuseau horaire est crucial car, à tout moment, la date varie d'un pays à l'autre. Par exemple, quelques instants après minuit à Paris est un nouveau jour pour les parisiens mais reste «hier» à Montréal pour les canadiens.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );
LocalDate ldFromZdt = zdt.toLocalDate();
ZonedDateTime zdtStartOfDay = ldFromZdt.atStartOfDay( zoneId );

zdtStartOfDay.toString ()… 2008-01-01T00: 00: 00-05: 00 [Amérique/Montréal]

UTC

Pour visualiser ce moment à travers l'objectif du fuseau horaire UTC , extrayez un objet Instant . ZonedDateTime et Instant représenteront le même moment sur la timeline mais apparaîtront sous la forme de deux heures de l'horloge murale } _ _.

Instant est la classe de base des blocs de construction dans Java.time, toujours en UTC par définition. Utilisez cette classe fréquemment, car vous devriez généralement utiliser votre logique métier, votre stockage de données et votre échange de données en UTC.

Instant instant = zdtStartOfDay.toInstant();

instant.toString ()… 2008-01-01T05: 00: 00Z

Nous voyons 5 heures du matin plutôt que minuit. En format standard, la variable Z à la fin est l'abréviation de Zulu et signifie «UTC».


À propos de Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes gênantes héritées _ date-heure telles que Java.util.Date , Calendar _, & SimpleDateFormat .

Le projet Joda-Time , désormais en mode { mode maintenance }, conseille la migration vers les classes Java.time .

Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .

Vous pouvez échanger des objets Java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou une version ultérieure. Pas besoin de chaînes, pas besoin de Java.sql.* classes.

Où obtenir les classes Java.time? 

  • Java SE 8 , Java SE 9 et versions ultérieures
    • Intégré. 
    • Une partie de l'API Java standard avec une implémentation fournie.
    • Java 9 ajoute quelques fonctionnalités et corrections mineures.
  • Java SE 6 et Java SE 7
    • Une grande partie de la fonctionnalité Java.time est rétroportée vers Java 6 et 7 dans ThreeTen-Backport .
  • Android
    • Les versions ultérieures d'Android regroupent des implémentations des classes Java.time.
    • Pour les anciens Android (<26), le projet ThreeTenABP s’adapte ThreeTen-Backport (mentionné ci-dessus). Voir Comment utiliser ThreeTenABP… .

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d’essai pour d’éventuels ajouts à Java.time. Vous pouvez y trouver des classes utiles telles que Interval _, YearWeek , YearQuarter _ et plus _.

3
Basil Bourque

La question est contradictoire. Il demande une date sans heure de la journée mais affiche un exemple avec une heure de 00:00:00.

Joda-Time

UPDATE: Le projet Joda-Time est maintenant en mode maintenance , avec l'équipe conseillant la migration vers les classes Java.time . Voir mon autre réponse pour la solution Java.time.

Si vous souhaitez plutôt que l'heure du jour soit réglée au premier moment de la journée, utilisez un objet DateTime sur la bibliothèque Joda-Time et appelez sa méthode withTimeAtStartOfDay . Sachez que le premier moment n'est peut-être pas l'heure 00:00:00 à cause de l'heure d'été ou d'autres anomalies.

2
Basil Bourque

Utilisez la méthode set() de la classe Calendar pour définir les champs HOUR_OF_DAY, MINUTE, SECOND et MILLISECOND sur zéro.

2
Michael Borgwardt

Vous pouvez le faire pour éviter les problèmes de fuseau horaire:

public static Date truncDate(Date date) {
    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    cal.setTime(date);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    return cal.getTime();
}

Bien que l’objet Java Date soit une valeur d’horodatage, il sera converti en fuseau horaire local lors de la troncature. Vous obtiendrez donc une valeur surprenante si vous attendez une valeur du fuseau horaire UTC.

1
GMsoF

Juste clear() champs redondants.

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.clear(Calendar.MINUTE);
calendar.clear(Calendar.SECOND);
calendar.clear(Calendar.MILLISECOND);
Date truncatedDate = calendar.getTime();
1
m190

Cela m'a vraiment ennuyé que le nouveau constructeur de calendrier "amélioré" ne prenne pas un int pendant des millisecondes comme le "terrible" vieux Date un . Je me suis alors vraiment contrarié et a écrit ceci:

long stuffYou = startTime.getTimeInMillis() % 1000;
startTime.setTimeInMillis(startTime.getTimeInMillis() - stuffYou);

Je n'ai pas utilisé le mot "truc" à l'époque, mais Puis j'ai découvert le bonheur de ceci:

startTime.set(Calendar.MILLISECOND, 0);

Mais je suis encore assez mécontent de ça.

1
Dave

Voici un moyen simple d’obtenir une date sans heure si vous utilisez Java 8+: utilisez le type Java.time.LocalDate au lieu de Rendez-vous amoureux.

LocalDate now = LocalDate.now();
 System.out.println(now.toString());

Le résultat:

2019-05-30

https://docs.Oracle.com/javase/8/docs/api/Java/time/LocalDate.html

0
Amy Doxy

Peut-être une réponse tardive, mais voici un moyen de le faire en une seule ligne sans utiliser aucune bibliothèque:

new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(YOUR_TIMESTAMP))
0
Alex

Pour toutes les réponses utilisant Calendar, vous devriez plutôt l'utiliser comme ceci

public static Date truncateDate(Date date) {
    Calendar c = Calendar.getInstance();
    c.setTime(date);
    c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY));
    c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE));
    c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND));
    c.set(Calendar.MILLISECOND, c.getActualMinimum(Calendar.MILLISECOND));
    return c.getTime();
}

Mais je préfère ceci:

public static Date truncateDate(Date date) {
    return new Java.sql.Date(date.getTime());
}
0
Guest

J'ai résolu le problème de la manière suivante (dans la zone de l'Est des huit (heure de Beijing)):

private Date getTruncatedDate(Date d) {
    if (d == null) {
        return null;
    }
    long h = 60 * 60 * 1000L;
    long dateStamp = d.getTime() - (d.getTime() + 8 * h) % (24 * h);
    return new Date(dateStamp);
}

Tout d’abord, vous devez bien préciser l’horodatage . L’horodatage est le nombre total de millisecondes entre le 01 janvier 00:00:00 et 19 h 00 (identique à l’UTC) ou le jeudi 01 janvier à 08:00:00 CST 1970 jusqu'à maintenant. 

N'oubliez pas: l'horodatage est indépendant du fuseau horaire.

Vous obtenez donc le même résultat avec la déclaration suivante dans différents fuseaux horaires:

System.out.println(new Date().getTime());

Et 

System.out.println(new Date(0));

imprime différentes informations sur l’heure dans différents fuseaux horaires: Si vous définissez le fuseau horaire de votre ordinateur sur UTC, 

Thu Jan 01 00:00:00 UTC 1970

Mais si vous définissez le fuseau horaire sur (UTC +8: 00) Beijing, Chongqing, Hong Kong, Urumq, vous obtenez:

Thu Jan 01 08:00:00 CST 1970

Java obtient l'horodatage, puis affiche les informations de date et d'heure en fonction du fuseau horaire.

Pour expliquer comment Java affiche les informations de date et d’heure dans différents fuseaux horaires, il est facile de retranscrire les informations sur l’heure. Vous devriez obtenir l'horodatage et prendre en compte le fuseau horaire lorsque l'information sur l'heure est coupée. Ensuite, vous pouvez créer un nouvel objet Date avec l’horodatage (nous pouvons l’appeler horodatage), Java compensera le fuseau horaire lorsqu’il affiche les informations de date.

Comme dans la zone Est des huit (heure de Beijing), l'heure de Beijing est antérieure de 8 heures à l'heure GMT. Vous devez donc soustraire plus de 8 heures lorsque vous effectuez l'opération Modulo. C’est-à-dire que vous devez commencer par obtenir l’heure GMT, puis Java ajoutera 8 heures lorsque l’heure d’affichage est basée sur le réglage du fuseau horaire de votre ordinateur.


La question du fuseau horaire est obscure et me laisse perplexe pendant longtemps. Maintenant, je le fais bien comprendre… L'espoir aide.


2018-01-04 La méthode ci-dessous fonctionne également.

private Date getTruncatedDate2(Date d) {
    Calendar cal = Calendar.getInstance(); // locale-specific
    cal.setTime(d);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);


return cal.getTime();

}

0
Gelbert

Avec Joda-Time depuis la version 2.0, vous pouvez utiliser LocalDate.toDate().

Simplement

// someDatetime is whatever Java.util.Date you have.
Date someDay = new LocalDate(someDatetime).toDate();
0
lamusique