web-dev-qa-db-fra.com

Y renvoie 2012 tandis que y renvoie 2011 dans SimpleDateFormat

Je me demande pourquoi "Y" renvoie 2012 alors que "y" renvoie 2011 dans SimpleDateFormat:

System.out.println(new SimpleDateFormat("Y").format(new Date())); // prints 2012
System.out.println(new SimpleDateFormat("y").format(new Date())); // prints 2011

Quelqu'un peut-il expliquer pourquoi?

73
Eng.Fouad

semaine année et année. De javadoc

Une année de semaine est synchronisée avec un cycle WEEK_OF_YEAR. Toutes les semaines entre la première et la dernière semaine (inclusivement) ont la même valeur d'année de semaine. Par conséquent, les premier et dernier jours d'une semaine peuvent avoir des valeurs d'année civile différentes.

Par exemple, le 1er janvier 1998 est un jeudi. Si getFirstDayOfWeek () est LUNDI et getMinimalDaysInFirstWeek () est 4 (paramètre compatible avec la norme ISO 8601), la semaine 1 de 1998 commence le 29 décembre 1997 et se termine le 4 janvier 1998. L'année de la semaine est 1998 pour les trois derniers jours. de l'année civile 1997. Si, cependant, getFirstDayOfWeek () est DIMANCHE, la semaine 1 de 1998 commence le 4 janvier 1998 et se termine le 10 janvier 1998; les trois premiers jours de 1998 font alors partie de la semaine 53 de 1997 et leur année de semaine est 1997.

78
Aravind R. Yarram

Voici une mise à jour Java 8 avec du code, car GregorianCalendar sera probablement obsolète ou supprimé des futures versions de JDK.

Le nouveau code est géré dans la classe WeekFields, et spécifiquement pour les minuscules y/majuscules Y avec weekBasedYear() accesseur de champ.

Renvoie un champ pour accéder à l'année d'une semaine sur la base de ce WeekFields. Cela représente le concept de l'année où les semaines commencent un jour de la semaine fixe, comme le lundi et chaque semaine appartient à exactement une année. Ce champ est généralement utilisé avec dayOfWeek () et weekOfWeekBasedYear ().

La première semaine (1) est la semaine commençant le getFirstDayOfWeek () où il y a au moins getMinimalDaysInFirstWeek () jours dans l'année. Ainsi, la première semaine peut commencer avant le début de l'année. Si la première semaine commence après le début de l'année, la période précédente se situe dans la dernière semaine de l'année précédente.

Ce champ peut être utilisé avec n'importe quel système de calendrier.

Dans la phase de résolution de l'analyse, une date peut être créée à partir d'une année, d'une semaine et d'un jour de la semaine.

En mode strict, les trois champs sont validés par rapport à leur plage de valeurs valides. Le champ semaine de l'année est validé pour garantir que l'année de la semaine résultante est l'année de la semaine demandée.

En mode intelligent, les trois champs sont validés par rapport à leur plage de valeurs valides. Le champ de l'année de la semaine est validé de 1 à 53, ce qui signifie que la date résultante peut être de l'année de la semaine suivante à celle spécifiée.

En mode indulgent, l'année et le jour de la semaine sont validés par rapport à la plage de valeurs valides. La date résultante est calculée équivalente à l'approche en trois étapes suivante. Tout d'abord, créez une date le premier jour de la première semaine de l'année hebdomadaire demandée. Prenez ensuite l'année basée sur la semaine, soustrayez-en une et ajoutez le montant en semaines à la date. Enfin, ajustez le bon jour de la semaine au sein de la semaine localisée.

La configuration de cette instance WeekFields dépend des paramètres régionaux et peut avoir différents paramètres selon elle, les pays américains et européens comme la France peuvent avoir un jour différent en début de semaine.

Par exemple, le DateFormatterBuilder de Java 8, instanciez l'analyseur avec les paramètres régionaux et utilisez ce paramètre régional pour le symbole Y:

public final class DateTimeFormatterBuilder {
    ...

    private void parsePattern(String pattern) {
        ...
                } else if (cur == 'Y') {
                    // Fields defined by Locale
                    appendInternal(new WeekBasedFieldPrinterParser(cur, count));
                } else {
        ...


    static final class WeekBasedFieldPrinterParser implements DateTimePrinterParser {
        ...

        /**
         * Gets the printerParser to use based on the field and the locale.
         *
         * @param locale  the locale to use, not null
         * @return the formatter, not null
         * @throws IllegalArgumentException if the formatter cannot be found
         */
        private DateTimePrinterParser printerParser(Locale locale) {
            WeekFields weekDef = WeekFields.of(locale);
            TemporalField field = null;
            switch (chr) {
                case 'Y':
                    field = weekDef.weekBasedYear();
                    if (count == 2) {
                        return new ReducedPrinterParser(field, 2, 2, 0, ReducedPrinterParser.BASE_DATE, 0);
                    } else {
                        return new NumberPrinterParser(field, count, 19,
                                                       (count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD, -1);
                    }
                case 'e':
                case 'c':
                    field = weekDef.dayOfWeek();
                    break;
                case 'w':
                    field = weekDef.weekOfWeekBasedYear();
                    break;
                case 'W':
                    field = weekDef.weekOfMonth();
                    break;
                default:
                    throw new IllegalStateException("unreachable");
            }
            return new NumberPrinterParser(field, (count == 2 ? 2 : 1), 2, SignStyle.NOT_NEGATIVE);
        }

        ...
    }

    ...
}

Voici un exemple

System.out.format("Conundrum                         : %s%n",
                  ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
                               .format(DateTimeFormatter.ofPattern("YYYYMMdd'T'HHmms'S'")));
System.out.format("Solution                          : %s%n",
                  ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
                               .format(DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmms'S'")));


System.out.format("JVM Locale first day of week      : %s%n",
                  WeekFields.of(Locale.getDefault()).getFirstDayOfWeek());
System.out.format("US first day of week              : %s%n",
                  WeekFields.of(Locale.US).getFirstDayOfWeek());
System.out.format("France first day of week          : %s%n",
                  WeekFields.of(Locale.FRANCE).getFirstDayOfWeek());
System.out.format("JVM Locale min days in 1st week   : %s%n",
                  WeekFields.of(Locale.getDefault()).getMinimalDaysInFirstWeek());
System.out.format("US min days in 1st week           : %s%n",
                  WeekFields.of(Locale.US).getMinimalDaysInFirstWeek());
System.out.format("JVM Locale min days in 1st week   : %s%n",
                  WeekFields.of(Locale.FRANCE).getMinimalDaysInFirstWeek());

System.out.format("JVM Locale week based year (big Y): %s%n",
                  ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC")).get(WeekFields.of(Locale.FRANCE).weekBasedYear()));
System.out.format("France week based year (big Y)    : %s%n",
                  ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC")).get(WeekFields.of(Locale.FRANCE).weekBasedYear()));
System.out.format("US week based year (big Y)        : %s%n",
                  ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC")).get(WeekFields.of(Locale.US).weekBasedYear()));

Et en ce qui concerne les paramètres régionaux et les majuscules Y, vous pouvez jouer avec l'option de ligne de commande -Duser.language= (fr, en, es, etc.), ou forcez les paramètres régionaux au moment de l'appel:

System.out.format("English localized                 : %s%n",
                  ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
                               .format(DateTimeFormatter.ofPattern("YYYYMMdd'T'HHmms'S'", Locale.ENGLISH)));
System.out.format("French localized                  : %s%n",
                  ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
                               .format(DateTimeFormatter.ofPattern("YYYYMMdd'T'HHmms'S'", Locale.FRENCH)));
11
Brice

Formater Y pour obtenir l'année de la semaine si le calendrier prend en charge l'année de la semaine. (getCalendar().isWeekDateSupported())

5
adatapost

J'ai appris à la dure la bibliothèque de balises JSTL format:date avec short car le format demandé utilise YYYY sous les couvertures. Ce qui peut en effet faire avancer la date imprimée d'un an.

1
Erica Kane