Joda Time LocalTime de 24:00 en fin de journée
Nous sommes en train de créer une application de planification et nous avons besoin de représenter quelqu'un est disponible à l'annexe au cours de la journée, peu importe l'heure de la zone ils sont. S'inspirant de Joda de Temps d'Intervalle, ce qui représente un intervalle de temps absolu entre les deux instances (démarrer inclusive, à la fin de l'exclusivité), nous avons créé un LocalInterval. Le LocalInterval est composé de deux LocalTimes (démarrer inclusive, à la fin de l'exclusivité), et nous avons même fait une pratique de classe pour la persistance de cette en mise en veille prolongée.
Par exemple, si quelqu'un est disponible à partir de 1:00 à 5:00, nous donnerait:
new LocalInterval(new LocalTime(13, 0), new LocalTime(17, 0));
Jusqu'ici tout va bien---jusqu'à ce que quelqu'un veut être disponible à partir de 11:00 jusqu'à minuit sur un jour. Depuis la fin d'un intervalle est exclusif, ce devrait être facilement représentées en tant que telles:
new LocalInterval(new LocalTime(23, 0), new LocalTime(24, 0));
Ack! Sans aller. Cela lève une exception, parce que LocalTime ne peut pas tenir une heure de plus de 23.
Cela semble être un défaut de conception de moi---Joda ne pense pas que quelqu'un peut vouloir un LocalTime qui représente un non-inclusive point de terminaison.
C'est vraiment frustrant, comme il souffle un trou dans ce qui était par ailleurs un très élégant modèle que nous avons créé.
Quelles sont mes options---autres que de bifurquer Joda et de prendre le contrôle de 24 heures? (Non, je n'aime pas la possibilité d'utiliser une valeur factice---dire 23:59:59---pour représenter 24:00.)
Mise à jour: Pour ceux qui ne cessent de dire qu'il n'y a pas une telle chose comme 24:00, voici une citation de la norme ISO 8601-2004 4.2.3 Notes 2,3: "La fin d'un calendrier jour [24:00] coïncide avec [00:00] au début du jour suivant ..." et les "Représentations où [hh] avec la valeur [24] ne sont privilégiées pour représenter la fin d'un intervalle de temps ...."
source d'informationauteur Garret Wilson | 2011-03-21
Vous devez vous connecter pour publier un commentaire.
La solution que nous avons finalement allé avec était d'utiliser 00:00 à 24:00, avec une logique tout au long de la classe et le reste de l'application d'interpréter cette valeur locale. C'est un vrai bidouille, mais c'est le moins intrusif et le plus élégant de chose que je pouvais venir.
Tout d'abord, le LocalTimeInterval classe conserve un indicateur interne de savoir si l'intervalle de point de terminaison est en fin de journée à minuit (24:00). Cet indicateur n'est vrai que si l'heure de fin de 00:00 (égal à LocalTime.MINUIT).
Par défaut, le constructeur estime 00:00 pour être en début de journée, mais il y a un autre constructeur pour la création manuelle d'un intervalle qui va tous les jours:
Il ya une raison pourquoi ce constructeur n'est pas seulement un temps de début et un "est en fin de journée" drapeau: lorsqu'il est utilisé avec une INTERFACE utilisateur avec une liste déroulante de fois, nous ne savons pas si l'utilisateur choisit 00:00 (ce qui est rendu de 24:00), mais nous savons que si la liste déroulante est pour la fin de la plage, dans notre cas d'utilisation, cela signifie 24:00. (Bien que LocalTimeInterval permet des intervalles vides, nous ne leur permettons pas à notre demande.)
Chevauchement de la vérification nécessite une logique spéciale pour prendre soin de 24:00:
De même, la conversion à un Intervalle absolu nécessite l'ajout d'un autre jour pour le résultat, si isEndOfDay() renvoie la valeur true. Il est important que le code de l'application ne jamais construit un Intervalle manuellement à partir d'un LocalTimeInterval de début et de fin des valeurs, comme la fin des temps peut indiquer la fin de la journée:
Lors de la persistance LocalTimeInterval dans la base de données, nous avons été en mesure de faire de la bidouille totalement transparent, que la mise en veille et SQL ont pas de 24:00 restriction (et n'ont aucune notion de LocalTime de toute façon). Si isEndOfDay() renvoie true, notre PersistentLocalTimeIntervalAsTime mise en œuvre stocke et récupère une vrai valeur de temps de 24:00:
et
Il est triste de constater que nous avons eu à écrire une solution de contournement, en premier lieu, c'est le meilleur que je pouvais faire.
Bien après 23:59:59 00:00:00 le jour suivant. Alors peut-être utiliser un
LocalTime
de0, 0
le jour suivant?Bien que depuis vos début et de fin sont inclus, 23:59:59 est vraiment ce que vous voulez de toute façon. Qui comprend la 59e seconde de la 59e minute du 23 heures, et se termine à la plage exactement sur 00:00:00.
Il n'y a pas une telle chose comme 24:00 (lors de l'utilisation de
LocalTime
).Ce n'est pas un défaut de conception.
LocalDate
ne gère pas les(24,0)
car il n'y a pas une telle chose comme 24:00.Aussi, ce qui arrive quand vous voulez représenter un intervalle entre 9h et 3h du matin?
Quel est le problème avec ceci:
Vous suffit de manipuler la possibilité que le temps de la fin, peut-être "avant" l'heure de début, et ajouter un jour lorsque nécessaire, et espère juste que personne ne veut représenter un intervalle de plus de 24 heures.
Sinon, représentent l'intervalle de la combinaison d'une
LocalDate
et unDuration
ouPeriod
. Qui enlève les "plus de 24 heures" problème.Votre problème peut être formulé comme la définition d'un intervalle sur un domaine qui s'enroule autour de. Votre min est 00:00, et votre max est de 24:00 (non inclus).
Supposons que votre intervalle est défini comme (inférieure, supérieure). Si vous avez besoin que la baisse des < empeigne, vous pouvez représenter (21:00, 24:00), mais vous êtes toujours incapable de représenter (21:00, 02:00), un intervalle qui encapsule dans le min/max limite.
Je ne sais pas si votre application de planification impliquerait wrap-around intervalles, mais si vous allez à aller à (21:00, 24:00) sans impliquer les jours, je ne vois pas ce qui vous empêche exigeant (21:00, 02:00) sans impliquer jours (conduisant ainsi à une synthèse autour de la dimension).
Si votre conception est susceptible d'une synthèse autour de la mise en œuvre, l'intervalle opérateurs sont tout à fait banale.
Par exemple (en pseudo-code):
Dans ce cas, j'ai trouvé que le fait d'écrire un wrapper autour de Joda-Time en œuvre les opérateurs est assez simple, et réduit l'impédance entre la pensée/mathématiques et de l'API. Même si c'est juste pour l'inclusion de 24:00 00:00.
Je suis d'accord que l'exclusion de 24:00 m'a ennuyé au début, et ça va être sympa si quelqu'un a offert une solution. Heureusement pour moi, vu que mon utilisation des intervalles de temps est dominé par de synthèse autour de la sémantique, je finis toujours avec un wrapper, qui, incidemment, résout le 24:00 exclusion.
Le temps de 24:00 est difficile. Alors que nous, les humains peuvent comprendre ce qu'on entend, le codage d'une API pour la représenter, sans nuire à tout le reste me paraît presque impossible.
La valeur 24 nullité est profondément codé en Joda-Time - essayez de l'enlever aurait des répercussions négatives dans beaucoup d'endroits. Je ne vous recommande pas d'essayer de le faire.
Pour votre problème, les locaux de l'intervalle doit être composé soit d'
(LocalTime, LocalTime, Days)
ou(LocalTime, Period)
. Ce dernier est légèrement plus souple. Ceci est nécessaire pour correctement prendre en charge un intervalle à partir de 23:00 à 03:00.Je trouve JodaStephenproposition de
(LocalTime, LocalTime, Days)
acceptable.Considérant le 13 Mars 2011 et de votre disponibilité le dimanche à partir de 00:00-12:00, vous auriez
(00:00, 12:00, 0)
qui étaient, en fait, de 11 heures à cause de l'heure d'été.Une disponibilité à partir de 15:00-24:00 vous pouvez ensuite le code que
(15:00, 00:00, 1)
qui serait étendu à 2011-03-13T15:00 - 2011-03-14T00:00 dont la fin serait souhaitée 2011-03-13T24:00. Cela signifie que vous utilisez un LocalTime de 00:00 le jour suivant, comme déjà aroth proposé.Bien sûr, il serait bien d'utiliser un 24:00 LocalTime directement et ISO 8601 conforme mais cela ne semble pas possible sans changer d'un lot à l'intérieur de JodaTime si cette approche semble un moindre mal.
Et dernier mais pas moins que vous pouvez encore étendre la barrière d'une seule journée, avec quelque chose comme
(16:00, 05:00, 1)
...c'est notre mise en œuvre de TimeInterval, utiliser la valeur null à la Date de fin de fin de journée. Il prend en charge les chevauchements() et() les méthodes et repose également sur la joda-time. Il prend en charge les intervalles s'étendant sur plusieurs jours.
Pour le bien de l'intégralité de ce test échoue:
Cela signifie que le MINUIT constante n'est pas très utile pour le problème, comme quelqu'un l'a suggéré.
Cette question est ancienne, mais beaucoup de ces réponses se concentrent sur Joda Temps, et en partie seulement aborder le vrai problème sous-jacent:
Le modèle dans le cas des OP code ne correspond pas à la réalité, c'est la modélisation.
Malheureusement, puisque vous ne semblent se soucier de la condition à la limite entre les jours, votre "autrement élégant modèle" n'est pas un bon match pour le problème de la modélisation. Vous avez utilisé une paire de valeurs de temps pour représenter les intervalles. Tenter de simplifier le modèle vers le bas pour une paire de fois est de simplifier en dessous de la complexité du monde réel problème. Les limites de la journée en fait n'existent pas dans la réalité et une paire de fois perd ce type d'informations. Comme toujours, sur la simplification des résultats dans la suite de la complexité de restaurer ou compenser pour le manque d'informations. Réelle complexité ne peut être poussé autour d'une partie du code à l'autre.
La complexité de la réalité ne peut être éliminé à la magie de la "non prise en charge des cas d'utilisation".
Votre modèle n'a de sens que dans un espace-problème où l'on n'a pas de soins de combien de jours peuvent exister entre le début et la fin des temps. Le problème de l'espace ne correspond pas à la plupart des problèmes du monde réel. Par conséquent, il n'est pas surprenant que Joda Temps, ne le supporte pas bien. L'utilisation de 25 valeurs pour les heures place (0-24) est un odeur de code et généralement des points de faiblesse dans la conception. Il y a seulement 24 heures dans la journée pour 25 valeurs ne doivent pas être besoin!
Noter que, puisque vous n'êtes pas capturer de la date de la fin de l'
LocalInterval
votre classe également ne pas obtenir suffisamment d'information pour tenir compte de l'heure d'été.[00:30:00 TO 04:00:00)
est généralement de 3,5 heures, mais pourrait également être de 2,5, ou 4,5 heures de temps.Vous devez soit utiliser une date/heure de début et la durée, ou à une date/heure de début et une date/heure de fin (inclus démarrer, exclusive est un bon choix par défaut). À l'aide d'une durée devient difficile si vous avez l'intention d'afficher l'heure de fin à cause de choses comme l'heure d'été, les années bissextiles et les secondes intercalaires. Sur l'autre main à l'aide d'une date de fin devient tout aussi difficile si vous prévoyez d'afficher la durée. Stocker à la fois des cours est dangereux parce qu'il viole les Principe SEC. Si j'avais écrit une telle classe je voudrais stocker une date/heure de fin et encapsulent la logique de l'obtention de la durée par l'intermédiaire d'une méthode sur l'objet. De cette façon, les clients de la classe de la classe ne sont pas tous venir avec leur propre code pour calculer la durée.
J'avais le code d'un exemple, mais il y a une option encore meilleure. L'utilisation de la norme Intervalle de Classe de Joda time, qui accepte d'ores et déjà un démarrage instantané et soit la durée ou à la fin de l'instantané. Il sera également et heureusement calculer la durée ou l'heure de fin pour vous. Malheureusement JSR 310 ne pas avoir un intervalle ou d'une catégorie similaire. (bien que l'on peut utiliser ThreeTenExtra à faire pour que)
Relativement lumineux gens à Joda Temps et de Sun/Oracle (JSR 310) à la fois très soigneusement réfléchi à ces problèmes. Vous pourriez être plus intelligent qu'eux. Il est possible de faire. Cependant, même si vous êtes un des plus lumineux de l'ampoule, votre 1 heure ne va probablement pas à accomplir ce qu'ils ont passé des années sur. Sauf si vous êtes quelque part dans un ésotérisme bord de cas, il est généralement gaspillage de temps et d'argent à dépenser l'effort de deuxième deviner. (bien sûr, au moment de l'OP JSR 310 n'était pas complet...)
Espérons-le, ci-dessus va aider les gens qui trouvent cette question lors de la conception ou de la fixation des problèmes similaires.