J'ai un problème de réinitialisation des heures en Java. Pour une date donnée, je souhaite régler les heures sur 00:00:00.
Ceci est mon code:
/**
* 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();
}
Le problème est que parfois, le temps est 12:00:00
et parfois, il s'agit de 00:00:00
et lorsque je demande à la base de données une entité enregistrée sur 07.02.2013 00:00:00
et que le temps réel de l'entité, stocké, est 12:00:00
, la requête échoue.
Je sais que 12:00:00 == 00:00:00
!
J'utilise AppEngine. Est-ce un bug d'appariement, un problème ou un autre problème? Ou cela dépend-il de quelque chose d'autre?
Utilisez une autre constante au lieu de Calendar.HOUR
, utilisez Calendar.HOUR_OF_DAY
.
calendar.set(Calendar.HOUR_OF_DAY, 0);
Calendar.HOUR
utilise 0-11 (pour une utilisation avec AM/PM), et Calendar.HOUR_OF_DAY
utilise 0-23.
Pour citer les Javadocs:
public statique final int HEURE
Numéro de champ pour get et set indiquant l'heure du matin ou de l'après-midi. HEURE est utilisé pour les 12 heures horloge (0 - 11). Midi et minuit sont représentés par 0 et non par 12 . Par exemple, à 10: 04: 15,250 PM l’HEURE est 10.
et
finale publique statique int HOUR_OF_DAY
Numéro de champ pour get et set indiquant l'heure du jour. HOUR_OF_DAY est utilisé pour les 24 heures l'horloge. Par exemple, à 10: 04: 15,250 PM HOUR_OF_DAY a 22 ans.
Tests ("maintenant" est actuellement environ 23h53 le 23 juillet 2013, heure avancée du Pacifique):
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()));
}
}
Sortie:
$ javac Main.Java
$ Java Main
2013-07-23 12:00:00
2013-07-23 00:00:00
Utilisation de Java.time
framework intégré à Java 8 et versions ultérieures. Voir Tutoriel .
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 vous n'avez pas besoin de l'heure, envisagez d'utiliser LocalDate
class.
LocalDate.now(); # 2015-11-19
Voici quelques fonctions d’utilité que j’utilise précisément pour cela.
/**
* 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();
}
Vous feriez mieux de définir principalement le fuseau horaire sur le composant DateFormat comme ceci:
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
Ensuite, vous pouvez obtenir l'heure "00:00:00" en passant 0 millisecondes au formateur:
String time = dateFormat.format(0);
ou vous pouvez créer un objet Date:
Date date = new Date(0); // also pass milliseconds
String time = dateFormat.foramt(date);
ou vous pouvez avoir plus de possibilités en utilisant le composant Calendrier mais vous devez également définir le fuseau horaire GMT comme instance de calendrier
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());
Une autre façon Java 8:
LocalDateTime localDateTime = LocalDateTime.now().truncatedTo(ChronoUnit.HOURS);
Mais il est beaucoup plus utile d’éditer la date existante.
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.
Vous utilisez d'anciennes classes de date-heure terribles qui ont été supplantées il y a des années par les classes modernes Java.time définies dans JSR 310.
Date
➙ Instant
Un Java.util.Date
représente un moment en UTC. Son remplacement est Instant
. Appelez les nouvelles méthodes de conversion ajoutées aux anciennes classes.
Instant instant = myJavaUtilDate.toInstant() ;
Spécifiez le fuseau horaire dans lequel vous souhaitez donner un sens à votre nouvelle heure.
Spécifiez un nom de fuseau horaire correct au format Continent/Region
, tel que America/Montreal
, Africa/Casablanca
ou Pacific/Auckland
. N'utilisez jamais les abréviations de 2 à 4 lettres telles que EST
ou IST
, car elles sont et non , sans fuseaux horaires normaux. et même pas unique (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime
Appliquez le ZoneId
au Instant
pour obtenir un ZonedDateTime
. Même moment, même point sur la ligne de temps, mais heure différente.
ZonedDateTime zdt = instant.atZone( z ) ;
Vous avez demandé de changer l'heure. Appliquez un LocalTime
pour modifier toutes les parties de l'heure: heure, minute, seconde, fraction de seconde. Un nouveau ZonedDateTime
est instancié, avec des valeurs basées sur l'original. Les classes Java.time utilisent ce modèle objets immuables pour fournir sécurité du thread .
LocalTime lt = LocalTime.of( 15 , 30 ) ; // 3:30 PM.
ZonedDateTime zdtAtThreeThirty = zdt.with( lt ) ;
Mais vous avez spécifiquement demandé 00:00. Donc, apparemment, vous voulez le premier moment de la journée. Attention, certains jours dans certaines zones ne commencent pas à 00:00:00. Ils peuvent commencer à une autre heure, telle que 01:00:00, en raison d'anomalies telles que l'heure d'été (DST).
Laissons Java.time déterminer le premier moment. Extrayez la partie date uniquement. Puis passez le fuseau horaire pour obtenir le premier moment.
LocalDate ld = zdt.toLocalDate() ;
ZonedDateTime zdtFirstMomentOfDay = ld.atStartOfDay( z ) ;
Si vous devez revenir en UTC, extrayez un Instant
.
Instant instant = zdtFirstMomentOfDay.toInstant() ;
Instant
➙ Date
Si vous avez besoin d'un Java.util.Date
pour interagir avec un ancien code non encore mis à jour, convertissez Java.time .
Java.util.Date d = Java.util.Date.from( instant ) ;
Nous pouvons définir Java.util.Date time part sur 00:00:00 en utilisant la classe LocalDate de Java 8/api Joda-datetime :
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
Cela pourrait être plus facile (en Java 8)
LocalTime.ofNanoOfDay(0)
Comme Java8 ajoute de nouvelles fonctions Date, nous pouvons le faire facilement.
// 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
Si vous avez besoin du format 00:00:00 en chaîne, vous devez utiliser SimpleDateFormat comme ci-dessous. Utiliser "H" à la place 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
Vous pouvez le faire avec les éléments suivants:
Calendar cal = Calendar.getInstance();
cal.set(year, month, dayOfMonth, 0, 0, 0);
Date date = cal.getTime();
Une autre façon de faire serait d'utiliser un DateFormat sans secondes:
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;
}