Comment analyser la date de la chaîne avec l'année et la semaine en utilisant java.temps


Dans l'ancien java, je peux le faire de cette façon:

System.out.println(new SimpleDateFormat("yyyy w", Locale.UK).parse("2015 1"));
// shows Mon Dec 29 00:00:00 CET 2014

System.out.println(new SimpleDateFormat("yyyy w", Locale.US).parse("2015 1"));
// shows Mon Dec 28 00:00:00 CET 2014

Je voudrais utiliser java.temps dans Java 8.

System.out.println( LocalDate.parse("2015 1", DateTimeFormatter.ofPattern("yyyy w", Locale.US)));

Résultat:

Java.temps.format.DateTimeParseException: Le texte '2015 1' n'a pas pu être analysé: Impossible d'obtenir LocalDate à partir de TemporalAccessor: {WeekOfWeekBasedYear[WeekFields[SUNDAY,1]]=1, Year=2015},ISO de type java.temps.format.Analyse

Comment le faire en java.de temps?

De plus, je ne suis pas satisfait de devoir passer les paramètres régionaux pour déterminer le premier jour de la semaine: Lundi vs dimanche. Ce n'est pas une fonction de pays mais une fonction de calendrier. Je voudrais utiliser quelque chose comme java.temps.temporel.WeekFields.ISO pour montrer au monde que la semaine commence par lundi

J'ai trouvé un cas similaire: https://stackoverflow.com/questions/3941700/how-to-get-dates-of-a-week-i-know-week-number

Mais pas pour java.temps dans Java 8. De plus, la solution qui crée d'abord un objet date et définit plus tard la semaine correcte n'est pas élégante. Je veux créer la date finale en un coup.

Author: Community, 2015-01-13

3 answers

Réponse directe et solution:

System.out.println( 
  LocalDate.parse("2015 1", 
    new DateTimeFormatterBuilder().appendPattern("YYYY w")
    .parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
    .toFormatter()));
// output: 2014-12-29

Explications:

A) Vous devriez utiliser Y au lieu de y parce que vous êtes intéressé par ISO-8601-week-date, pas par year-of-era.

B) Une date de calendrier ne peut pas être formée en donnant simplement une année (basée sur la semaine) et un numéro de semaine. Le jour de la semaine est important pour déterminer le jour dans la semaine civile spécifiée. Le formateur prédéfini pour les dates de la semaine nécessite le jour de la semaine manquant. Vous devez donc construire un analyseur spécialisé utilisant le builder-pattern. Ensuite, il est nécessaire de dire à l'analyseur quel jour de la semaine est souhaité - via la méthode parseDefaulting().

C) J'insiste (et défends JSR-310 ici) en disant que la question quand une semaine commence n'est pas un problème de calendrier mais un problème dépendant du pays. Les États-Unis et la France (par exemple) utilisent le même calendrier mais ont des vues différentes sur la façon de définir une semaine. La norme ISO-8601 peut être appliquée en utilisant le champ explicitement référent ISO WeekFields.ISO.dayOfWeek(). Attention: Les tests ont révélé que l'utilisation de ChronoField.DAY_OF_WEEK avec Locale.ROOT ne semble pas toujours garantir un comportement ISO-semaine comme indiqué dans ma première version de cette réponse (les raisons ne sont pas encore claires pour moi-une vue rapprochée des sources semble être nécessaire pour éclairer le comportement non intuitif).

D) Le java-time-package le fait bien - à l'exception que Monday est juste spécifié comme numéro 1. J'aurais préféré l'enum. Ou utilisez l'énumération et sa méthode getValue().

E) Avis latéral: SimpleDateFormat se comporte avec indulgence par défaut. Le java-time-package est plus strict et refuse d'inventer un jour de semaine manquant à l'air libre-même en mode indulgent (ce qui est à mon avis plutôt une bonne chose). Le logiciel ne devrait pas deviner tellement, au lieu de cela, le programmeur devrait penser plus à quel jour de la semaine est le bon. Encore une fois ici: Les exigences de l'application seront probablement différentes aux États-Unis et en France sur le bon réglage par défaut.

 5
Author: Meno Hochschild, 2015-01-19 17:36:48

La réponse acceptée par Meno Hochschild est correcte. Voici un itinéraire alternatif.

YearWeek

Utiliser le YearWeek classe dans la bibliothèque ThreeTen-Extra . Cette bibliothèque étend java.temps avec des fonctionnalités supplémentaires. Cette classe particulière représente une année-semaine dans le ISO 8601 week date system.

La méthode factory YearWeek.of prend une paire d'arguments entiers, l'année basée sur la semaine et le numéro de la semaine.

YearWeek yw = YearWeek.of( 2015 , 1 );  

ISO 8601

Idéalement, vous utiliseriez des formats standard ISO 8601 pour les chaînes représentant des valeurs date-heure. Pour année-semaine ce serait yyyy-Www le numéro d'année basé sur la semaine, un trait d'union, un W et deux chiffres pour le numéro de semaine avec un remplissage zéro selon les besoins.

2015-W01

Le java.les classes de temps et les classes Threeeten-Extra utilisent les formats ISO 8601 standard par défaut lors de l'analyse et de la génération de chaînes. Donc, la vie est beaucoup plus facile si vous vous en tenez à la norme.

YearWeek yw = YearWeek.parse( "2015-W01" );
String output = yw.toString(); // 2015-W01

Analyse des entiers.

Vous avez un format non standard pour les nombres. Analysons donc votre chaîne en deux morceaux, un nombre chacun, à interpréter comme int entiers.

String string = "2015 1";
String[] parts = string.split(" "); // SPACE character.
String part1 = parts[0]; // 2015
String part2 = parts[1]; // 1

La classe Integer convertit ces chaînes en int valeurs primitives.

int weekBasedYearNumber = Integer.parseInt( part1 ) ;
int weekNumber = Integer.parseInt( part2 ) ;

Appelez maintenant cette méthode d'usine.

YearWeek yw = YearWeek.of( weekBasedYearNumber , weekNumber );

LocalDate

En ce qui concerne le premier jour de la semaine, nous avons discuté ici de la définition standard ISO 8601 de semaine. Dans cette définition, le lundi est toujours le premier jour, une semaine allant du lundi au dimanche. Semaine # 1 contient le premier jeudi de l'année civile. Dans le cas de 2015-W01, ce jeudi serait le 1er janvier 2015.

Donc, pas de Locale nécessaire.

Je ne suis pas tout à fait sûr de votre objectif, mais il semble extraire des dates particulières pour les jours de votre semaine. C'est assez facile avec la YearWeek la classe et le DayOfWeek enum.

LocalDate monday = yw.atDay( DayOfWeek.MONDAY );  // 2014-12-29 start-of-week.
LocalDate friday = yw.atDay( DayOfWeek.FRIDAY );  // 2015-01-02
LocalDate sunday = yw.atDay( DayOfWeek.SUNDAY );  // 2015-01-04 end-of-week.

capture d'écran du mois civil Janvier 2015 avec ISO 8601 semaine numéro 1 allant du lundi 29/12/2014 au dimanche 04/01/2015

 2
Author: Basil Bourque, 2017-05-23 12:17:25

Cela peut également être réalisé en mettant la valeur d'analyse par défaut pour le jour de la semaine en utilisant "ChronoField.Day_Of_Week " et en définissant la valeur comme "1" comme suit:

System.out.println( "Date From Year and Week : "+
              LocalDate.parse("2015 1", 
                new DateTimeFormatterBuilder().appendPattern("YYYY w")
                .parseDefaulting(ChronoField.DAY_OF_WEEK, 1)
                .toFormatter()));
 0
Author: KayV, 2017-07-26 09:47:48