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.
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();
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.
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.
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();
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.
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()
Utilisez DateUtils d’Apache, avec truncate, comme ceci:
DateUtils.truncate(Calendar.getInstance().getTime(), Calendar.DATE);
Pour les horodatages:
timestamp -= timestamp % (24 * 60 * 60 * 1000)
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);
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
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
Les autres réponses sont correctes, mais utilisez les anciennes classes date-heure désormais obsolètes du framework 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
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]
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».
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?
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 _.
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
.
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.
Utilisez la méthode set()
de la classe Calendar pour définir les champs HOUR_OF_DAY, MINUTE, SECOND
et MILLISECOND
sur zéro.
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.
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();
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.
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
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))
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());
}
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();
}
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();