Obtenez la date du premier jour de la semaine en fonction de LocalDate.maintenant () en Java 8


Je voudrais obtenir la date du premier jour de la semaine basé sur LocalDate.maintenant(). Ce qui suit était possible avec JodaTime, mais semble être supprimé de la nouvelle API de date dans Java 8.

LocalDate now = LocalDate.now();
System.out.println(now.withDayOfWeek(DateTimeConstants.MONDAY));

Je ne peux pas appeler 'withDayOfWeek()', car il n'existe pas.

Donc, ma question est: Comment obtenir la date du premier jour de la semaine en fonction de certains LocalDate?

Author: bashoogzaad, 2015-02-11

7 answers

Notez que l'expression System.out.println(now.with(DayOfWeek.MONDAY)) est indépendante des paramètres régionaux car elle utilise ISO-8601, donc elle saute toujours en arrière au lundi dernier (ou reste le lundi au cas où la date pointe déjà vers lundi).

En tant que tel aux États-Unis ou dans d'autres pays-où la semaine commence le dimanche-il se peut que cela ne fonctionne pas comme prévu - now.with(DayOfWeek.MONDAY) ne sautera pas en avant au lundi, au cas où la date pointerait vers le dimanche.

Si vous avez besoin de répondre à ces préoccupations, il est préférable d'utiliser le champ localisé WeekFields.Semaine():

LocalDate now = LocalDate.now();
TemporalField fieldISO = WeekFields.of(Locale.FRANCE).dayOfWeek();
System.out.println(now.with(fieldISO, 1)); // 2015-02-09 (Monday)

TemporalField fieldUS = WeekFields.of(Locale.US).dayOfWeek();
System.out.println(now.with(fieldUS, 1)); // 2015-02-08 (Sunday)

Un autre exemple dû aux commentaires ci-dessous:

LocalDate ld = LocalDate.of(2017, 8, 18); // Friday as original date

System.out.println(
    ld.with(DayOfWeek.SUNDAY)); // 2017-08-20 (2 days later according to ISO)

// Now let's again set the date to Sunday, but this time in a localized way...
// the method dayOfWeek() uses localized numbering (Sunday = 1 in US and = 7 in France)

System.out.println(ld.with(WeekFields.of(Locale.US).dayOfWeek(), 1L)); // 2017-08-13
System.out.println(ld.with(WeekFields.of(Locale.FRANCE).dayOfWeek(), 7L)); // 2017-08-20

L'exemple des États-Unis montre assez clairement que quelqu'un résidant aux États-Unis s'attendrait à aller au dernier et non au dimanche suivant, car le dimanche est considéré comme le premier jour de la semaine aux États-Unis. L'expression ISO simple with(DayOfWeek.SUNDAY) ignore ce problème de localisation.

 53
Author: Meno Hochschild, 2017-08-18 13:49:57

Essayer

System.out.println(now.with(DayOfWeek.MONDAY));
 11
Author: Ray, 2015-02-11 09:32:27

Malgré toutes les réponses précédentes, je devais encore creuser pour comprendre ce que Java8 faisait, alors voici ce que j'ai trouvé être la façon la plus intuitive de le faire:

LocalDate implémente Temporelle

with(TemporalField field, long newValue)

Renvoie un objet du même type que cet objet avec le champ spécifié modifié.

Nous devons donc lui dire quelle partie de date de LocalDate nous voulons changer (DAY_OF_WEEK) et changer en quoi valeur.

Au cas où vous auriez des doutes sur le fait que les jours de la semaine pourraient être comptés de 0 à 6 ou de 1 à 7:

    System.out.printf("first day of week (0 or 1) == %d \n",
            ChronoField.DAY_OF_WEEK.range().getMinimum());
first day of week (0 or 1) == 1 

J'ai dû déterminer ce que mon JDK fournissait pour les valeurs par défaut-YMMV:

    System.out.printf("default zone offset==[%s]\n",
            ZoneId.systemDefault());
    System.out.printf("1st day of week==%s\n",
            WeekFields.of(Locale.getDefault()).getFirstDayOfWeek());
default zone offset==[Europe/London]
1st day of week==MONDAY

Donc, si j'exécute du code basé sur ces valeurs par défaut, comme ceci:

    LocalDate localDate = LocalDate.now();
    System.out.printf("localDate == %s \n", localDate);
    System.out.printf("localdate first day of week == %s (%s) \n",
            localDate.with(ChronoField.DAY_OF_WEEK, 1),
            localDate.with(ChronoField.DAY_OF_WEEK, 1).getDayOfWeek());
localDate == 2017-10-24 
localdate first day of week == 2017-10-23 (MONDAY) 

Alors Java va avec ChronoField.DAY_OF_WEEK qui définit non seulement quelle partie de la date nous voulons modifier, mais aussi comment la modifier.

Donc si nous voulons que notre code traite de quoi que ce soit l'utilisateur spécifie que le premier jour de la semaine, nous créons notre propre définition de la façon dont les calculs basés sur la semaine sont destinés à être effectués, en utilisant la méthode d'usine WeekFields.of().

En utilisant cela, nous pouvons passer notre propre paramètre dayOfWeek à {[14] } pour faire le calcul de la date comme nous le voulons:

    TemporalField myWeek = WeekFields.of(DayOfWeek.SUNDAY, 1).dayOfWeek();
    System.out.printf("configured localdate first day of week == %s (%s) \n",
            localDate.with(myWeek, 1),
            localDate.with(myWeek, 1).getDayOfWeek());
configured localdate first day of week == 2017-10-22 (SUNDAY) 

Pour plus d'informations, jetez un oeil au code LocalDate.with(), c'est assez intéressant.

 2
Author: Adam, 2017-10-24 14:52:18

Grâce à venir à partir de dans cette question.

Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 0); // ! clear would not reset the hour of day !
        cal.clear(Calendar.MINUTE);
        cal.clear(Calendar.SECOND);
        cal.clear(Calendar.MILLISECOND);

        // get start of this week in milliseconds
        cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
        System.out.println("Start of this week:       " + cal.getTime());
        System.out.println("... in milliseconds:      " + cal.getTimeInMillis());
 1
Author: Semih Eker, 2017-05-23 12:34:37

Comme Réponse correcte par Ray dit, vous pouvez appeler with et passer le DayOfWeek enum.

Fuseau horaire

Notez que le fuseau horaire est crucial pour déterminer la date d ' "aujourd'hui". À tout moment, la date varie selon l'endroit où vous vous tenez sur le globe.

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate firstDayOfThisWeek = LocalDate.now ( zoneId ).with ( DayOfWeek.MONDAY );

Si vous ne spécifiez pas de fuseau horaire, le fuseau horaire par défaut actuel de la JVM est appliqué silencieusement. Attention: Cette valeur par défaut peut changer à tout moment pendant l'exécution! Mieux vaut spécifier votre fuseau horaire souhaité / attendu.

ZonedDateTime

, Vous pouvez appliquer un fuseau horaire (un ZoneId) pour votre LocalDate pour obtenir un ZonedDateTime représentant le premier moment de la semaine.

ZonedDateTime thisWeekStart = firstDayOfThisWeek.atStartOfDay ( zoneId );
 1
Author: Basil Bourque, 2017-05-23 11:47:15

Le LocalDate ne semble pas l'avoir, mais WeekFields (qui provient de l'API java-8) le fait (ici). Vous pouvez donc faire ceci:

WeekFields.of(Locale.getDefault()).firstDayOfWeek.value

Cela renvoie la valeur du premier jour de la semaine, à partir de 1 comme lundi, se terminant par 7 comme dimanche.

Exemple d'utilisation (dans Kotlin), pour obtenir un nouveau LocalDate qui a le dayOfWeek être défini, en arrière dans le temps au lieu de forward:

/**@param targetDayOfWeek day of week to go to, starting from 1 as Monday (and 7 is Sunday) */
fun LocalDate.minusDaysToDayOfWeek(targetDayOfWeek: Int = WeekFields.of(Locale.getDefault()).firstDayOfWeek.value): LocalDate {
    //conversion so that Sunday is 0, Monday is 1, etc:
    val diffDays = (dayOfWeek.value % 7) - (targetDayOfWeek % 7)
    val result = when {
        diffDays == 0 -> this
        diffDays < 0 -> minusDays((7 + diffDays).toLong())
        else -> minusDays(diffDays.toLong())
    }
    return result
}

Exemple entrées-sorties:

2017-12-31 -> 2017-12-31
2018-01-01 -> 2017-12-31
2018-01-02 -> 2017-12-31
2018-01-03 -> 2017-12-31
2018-01-04 -> 2017-12-31
2018-01-05 -> 2017-12-31
2018-01-06 -> 2017-12-31
2018-01-07 -> 2018-01-07
2018-01-08 -> 2018-01-07
2018-01-09 -> 2018-01-07
2018-01-10 -> 2018-01-07
2018-01-11 -> 2018-01-07
2018-01-12 -> 2018-01-07
2018-01-13 -> 2018-01-07
2018-01-14 -> 2018-01-14
2018-01-15 -> 2018-01-14

Et voici un exemple de fonction pour avancer dans le temps jusqu'au jour cible de la semaine:

fun LocalDate.plusDaysToDayOfWeek(targetDayOfWeek: Int = getLastDayOfWeek()): LocalDate {
    val diffDays = (targetDayOfWeek % 7) - (dayOfWeek.value % 7)
    val result = when {
        diffDays == 0 -> this
        diffDays < 0 -> plusDays((7 + diffDays).toLong())
        else -> plusDays(diffDays.toLong())
    }
    return result
}

/**@return the  last day of week, when 1 is Monday ... 7 is Sunday) */
@JvmStatic
fun getLastDayOfWeek(firstDayOfWeek: DayOfWeek = WeekFields.of(Locale.getDefault()).firstDayOfWeek): Int {
    return when (firstDayOfWeek) {
        DayOfWeek.MONDAY -> DayOfWeek.SUNDAY.value
        else -> firstDayOfWeek.value - 1
    }
}

BTW, ce qui est bizarre, c'est que je pense que le code dans les coulisses de la nouvelle API utilise de toute façon la classe Calendar...

Si vous détestez utiliser dayOfWeek comme utilisé pour LocalDate (comme je le fais), et que vous préférez celui utilisé avec Calendar, vous pouvez utiliser ces convertisseurs simples:

fun DayOfWeek.toCalendarDayOfWeek(): Int {
    return when (this) {
        DayOfWeek.SATURDAY -> Calendar.SATURDAY
        else -> (this.value + 1) % 7
    }
}

@JvmStatic
fun convertLocalDateDayOfWeekToCalendarDayOfWeek(localDateDayOfWeek: Int): Int {
    return when (localDateDayOfWeek) {
        DayOfWeek.SATURDAY.value -> Calendar.SATURDAY
        else -> (localDateDayOfWeek + 1) % 7
    }
}

@JvmStatic
fun convertFromCalendarDayOfWeekToLocalDateDayOfWeek(calendarDayOfWeek: Int): Int {
    return when (calendarDayOfWeek) {
        Calendar.SUNDAY -> DayOfWeek.SUNDAY.value
        else -> calendarDayOfWeek - 1
    }
}
 1
Author: android developer, 2018-01-14 12:38:55

Avec Joda Time, que pensez-vous de

now.toString("EEEE", locale)
 0
Author: Labe, 2016-02-19 17:24:50