2009-05-31 6 views
5

À partir d'une date donnée, j'ai besoin de calculer minuit de son jour. Voici ce que j'ai trouvé. C'est tellement moche que je me dis qu'il doit y avoir un meilleur moyen.Calcul d'un jour donné Date

private Date day(Date creation) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.setTime(creation); 
    calendar.set(Calendar.HOUR_OF_DAY, 0); 
    calendar.set(Calendar.MINUTE, 0); 
    calendar.set(Calendar.SECOND, 0); 
    calendar.set(Calendar.MILLISECOND, 0); 
    return calendar.getTime(); 
} 

Suggestions?

Kent

+3

Bon Dieu - d'abord Alan Kay, maintenant Kent Beck. SO est l'endroit à être ... – duffymo

+0

C'est pire que cela, le code que vous avez posté ne tient pas compte du fuseau horaire, ce qui vous intéresse ou non. – Yishai

+0

simple vérifier ceci [ici] (http://developer-dot-android.blogspot.com/2012/03/date-into-day-tutorial.html) –

Répondre

7

Vous devez considérer l'API de date intégrée obsolète. Utilisez plutôt l'API de date et heure Joda.

Voici un remplacement de votre méthode.

private Date day(Date creation) { 
    return new DateMidnight(creation).toDate(); 
} 

Voici un test simple:

public static void main(String[] args) { 
    final Date creation = new Date(); 
    final Date midnight = new Foobar().day(creation); 
    System.out.println("creation = " + creation); 
    System.out.println("midnight = " + midnight); 
} 

La sortie est:

creation = Sun May 31 10:09:38 CEST 2009  
midnight = Sun May 31 00:00:00 CEST 2009 
2

Si vous cherchez heure locale, c'est le meilleur que vous allez obtenir. Et même si vous pouvez le considérer comme moche, il se passe (potentiellement) beaucoup de choses dans les coulisses.

Si vous voulez minuit UTC, ce qui suit fonctionnera:

public static void main(String[] argv) 
throws Exception 
{ 
    final long MILLIS_PER_DAY = 24 * 3600 * 1000L; 

    long midnightUTC = (System.currentTimeMillis()/MILLIS_PER_DAY) * MILLIS_PER_DAY; 
} 

Modifier: Je ne vraiment recommande pas d'utiliser les dates locales dans le code "de production". Ils causent plus de problèmes qu'ils ne le méritent - pensez à une personne sur la côte ouest des États-Unis qui trouve soudainement son «jour» réduit de 3 heures parce qu'un ordinateur de la côte est a une idée différente de minuit.

5

JODA peut avoir une meilleure solution, au prix d'une autre dépendance à une bibliothèque. Je regarde son DateMidnight property. Je suis désolé de ne pouvoir répondre de façon plus formelle, mais je ne suis pas moi-même un utilisateur de JODA.

0

Je pense que la seule façon d'améliorer sensiblement ce code est de changer de représentation. Par exemple,

  • représenter le jour par le système "date absolue", explique par Nachum Dershowitz et Ed Reingold dans Calendrical Calculations.

  • Représente l'heure en comptant les secondes à partir de minuit. Ou si vous avez besoin d'une résolution inférieure à la seconde, comptez des millisecondes.

votre exemple bref je ne peux pas dire à quel point dans votre programme, vous devez être compatible avec Date et Calendar classes existantes, ou si vous pouvez créer une sous-classe utile en utilisant une représentation Saner.

0

Vous n'avez pas programmé Java depuis un certain temps, mais vous pouvez appeler set method en indiquant les valeurs actuelles pour l'année, le mois et le jour. Bien que de lire un peu plus près, vous devrez peut-être appeler d'abord clair. Cela peut ou peut ne pas être moins prolixe que d'utiliser votre méthode actuelle.

1

JODA est la voie à suivre si vous avez des besoins sérieux de calendrier, au moins jusqu'à ce que JSR-310 pénètre dans la JDK (1.7 peut-être, sinon 1.8).Cela étant dit, il y a quelques choses qui pourraient être faites pour rendre ce code un peu plus agréable.

import static java.util.Calendar.*; 

... 

private static final List<Integer> TIME_FIELDS = 
    Arrays.asList(HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND); 

private Date day(Date creation) { 
    Calendar c = getInstance(); 
    c.setTime(creation); 
    for(int field : TIME_FIELDS) c.set(field, 0); 
    return c.getTime(); 
} 

Cela ne va pas gagner des récompenses de performance. Vous pouvez faire un standard pour la boucle en vous basant sur les valeurs de champs spécifiques (la classe Calendar a un type FIELD_COUNT, ce qui implique que vous pouvez faire quelque chose comme ça), mais cela risque de poser des problèmes entre implémentations JDK et entre versions.

0

Ceci est juste le complément du code affiché à l'origine. Il définit l'année, le mois et le jour dans un nouvel objet GregorianCalendar, au lieu de tout effacer sauf l'année, le mois et le jour dans la variable de calendrier. Ce n'est pas vraiment une amélioration, mais je pense qu'il est plus clair de dire quels sont les champs que vous copiez, et non les champs que vous ignorez.

public Date day(Date creation) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.setTime(creation); 
    return new GregorianCalendar(
      calendar.get(Calendar.YEAR), 
      calendar.get(Calendar.MONTH), 
      calendar.get(Calendar.DAY_OF_MONTH)).getTime(); 
} 

Personnellement, je pense que j'irais avec la bibliothèque Joda proposée par d'autres.

1

Utilisation de la bibliothèque date4j:

DateTime start = dt.getStartOfDay(); 
Questions connexes