52 votes

Jodatime début de journée et fin de journée

Je veux créer un intervalle entre le début de la semaine et la fin de la semaine en cours.

J'ai le code suivant, emprunté à cette réponse :

private LocalDateTime calcNextSunday(LocalDateTime d) {
    if (d.getDayOfWeek() > DateTimeConstants.SUNDAY) {
        d = d.plusWeeks(1);
    }
    return d.withDayOfWeek(DateTimeConstants.SUNDAY);
}

private LocalDateTime calcPreviousMonday(LocalDateTime d) {
    if (d.getDayOfWeek() < DateTimeConstants.MONDAY) {
        d = d.minusWeeks(1);
    }
    return d.withDayOfWeek(DateTimeConstants.MONDAY);
}

Mais maintenant je veux le lundi LocalDateTime pour être à 00:00:00, et le dimanche LocalDateTime à 23:59:59. Comment dois-je m'y prendre ?

1 votes

C'est toujours un très mauvaise idée de soustraire une "petite unité" à la fin des intervalles de temps. Les intervalles de temps ont leur début inclus et leur fin exclue. Pour vérifier si une (date)heure est incluse dans l'intervalle, il faut faire : start <= time && time < end. Sinon, vous vous retrouvez avec une petite quantité de valeurs (effectivement dans l'intervalle) qui sont soudainement exclues. Pensez à la dernière seconde dans votre cas. 23:59:59.5 n'est pas dans cet intervalle. L'utilisation de petites unités permet simplement de réduire le nombre de valeurs exclues, mais ne supprime pas le problème. L'utilisation de la bonne comparaison le fait.

156voto

JodaStephen Points 6357

Vous pouvez utiliser le withTime méthode :

 d.withTime(0, 0, 0, 0);
 d.withTime(23, 59, 59, 999);

Même réponse que celle de Peter, mais plus courte.

52 votes

Le début de la journée peut également être obtenu avec d.withTimeAtStartOfDay()

16 votes

withTimeAtStartOfDay() n'est pas disponible pour LocalDateTime mais il est disponible pour [DateTime](http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html#withTimeAtStartOfDay())

0 votes

+1. Une remarque : LocalDateTime is immutable, so there are no set methods. Instead, this method returns a new instance with the value of millis of day changed. Vous devez donc affecter le résultat à une variable.

101voto

TheRueger Points 2192

Un autre moyen simple est

d.millisOfDay().withMaximumValue();

16 votes

Cette réponse devrait être acceptée car, comparée aux autres réponses, elle est la meilleure en termes de performances (moins d'objets créés car DateTime est inmutable). La documentation indique même que la méthode avec MaximunValue est la meilleure façon d'accomplir ce que la question demande.

0 votes

Quelle est la différence avec getMaximumValueOverall ?

25voto

Peter Liljenberg Points 3588

Pourquoi pas :

private LocalDateTime calcNextSunday(LocalDateTime d) {
    return d.withHourOfDay(23).withMinuteOfHour(59).withSecondOfMinute(59).withDayOfWeek(DateTimeConstants.SUNDAY);
}

private LocalDateTime calcPreviousMonday(final LocalDateTime d) {
    return d.withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withDayOfWeek(DateTimeConstants.MONDAY);
}

5 votes

setXxx par convention, n'a pas de type de retour en Java, ce qui ne permet pas le chaînage. Cela rappelle le modèle du constructeur (qui, à l'origine, ne fonctionnait pas sur un objet existant).

2 votes

En effet. Cela vous permet d'enchaîner les appels, plutôt que de les avoir tous sur des lignes différentes, et vous permet de bénéficier de tous les avantages des objets immuables.

0 votes

Je crois que le "modèle" s'appelle "interface fluide". martinfowler.com/bliki/FluentInterface.html - apporte beaucoup d'avantages en termes de lisibilité et de clarté à mon avis.

2voto

Cory Roy Points 3512

Avec Kotlin, vous pouvez écrire une fonction d'extension :

fun DateTime.withTimeAtEndOfDay() : DateTime = this.withTime(23,59,59,999)

Cela vous permettrait d'écrire :

d.withDayOfWeek(DateTimeConstants.SUNDAY).withTimeAtEndOfDay()

1voto

GreeneCreations Points 139

Pour ceux qui viennent ici à la recherche de la réponse à "js-joda", vous avez deux options en fonction de ce que vous cherchez à accomplir

Option 1 : Vous voulez que le début de la journée soit dans le même fuseau horaire.

Puisque vous avez choisi de calculer vos heures sur la base d'un instant par rapport à un fuseau horaire, vous devez utiliser ZonedDateTime :

import { ZonedDateTime, LocalDate, ZoneId, DateTimeFormatter} from "js-joda";
import 'js-joda-timezone';

const nowInNewYorkCity = ZonedDateTime.now(ZoneId.of("America/New_York"))
const startOfTodayInNYC = nowInNewYorkCity.truncatedTo(ChronoUnit.DAYS);
console.log(startOfTodayInNYC.toString()) // Prints "2019-04-15T00:00-04:00[America/New_York]"
// And if you want to print it in ISO format
console.log(startOfTodayInNYC.format(DateTimeFormatter.ISO_INSTANT)) // "2019-04-14T04:00:00Z"

Option 2 : Vous connaissez le jour exact pour lequel vous souhaitez obtenir l'heure.

Vous pouvez ensuite utiliser les méthodes suivantes à partir de LocalDate pour obtenir l'heure relative (c'est-à-dire ZonedDateTime) que vous souhaitez :

    atStartOfDay(): LocalDateTime
    atStartOfDay(zone: ZoneId): ZonedDateTime
    atStartOfDayWithZone(zone: ZoneId): ZonedDateTime

Option 3 : Je veux seulement le jour où l'instant s'est produit.

Remarquez qu'avec ce code, vous obtenez le jour qui correspond à l'endroit où vous vous trouvez. Ainsi, pour les habitants de New York, il s'agit de "2019-04-14" et pour ceux de Londres, il s'agit de "2019-04-15" (ce qui est génial !) parce que l'instant dans le temps se situe dans la période où il s'agit effectivement de demain à Londres ("2019-04-15T00:00:05Z"). Imaginez que vous appelez quelqu'un à Londres depuis New York, et que le Londonien vous dise : "Bon sang, pourquoi m'appelez-vous si tôt... il est minuit passé de 5 secondes".

import { ZonedDateTime, LocalDate, ZoneId} from "js-joda";
import 'js-joda-timezone';

const aTimeWhenLondonIsAlreadyInTomorrow = "2019-04-15T00:00:05.000Z";
const inBetweenTimeInLondon = ZonedDateTime.parse(aTimeWhenLondonIsAlreadyInTomorrow);
const inBetweenTimeInNYC = inBetweenTimeInLondon.withZoneSameInstant(ZoneId.of("America/New_York"))
const dayInLondon = inBetweenTimeInLondon.toLocalDate();
const dayInNYC = inBetweenTimeInNYC.toLocalDate();
console.log(inBetweenTimeInLondon.toString()); // "2019-04-15T00:00:05Z"
console.log(dayInLondon.toString()); // "2019-04-15"
console.log(inBetweenTimeInNYC.toString()) // "2019-04-14T20:00:05-04:00[America/New_York]"
console.log(dayInNYC.toString()); // "2019-04-14"

Références : https://js-joda.github.io/js-joda/class/src/LocalDate.js~LocalDate.html#instance-method-atStartOfDayWithZone

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X