Y 2012'yi döndürürken, SimpleDateFormat'ta 2011'i döndürür


85

Merak ediyorum, neden 'Y' 2012'yi, 'y' ise 2011'i SimpleDateFormat:

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

Herhangi biri nedenini açıklayabilir mi?


40
Gelecekteki okuyuculara bir not olarak: Bu davranış yalnızca yılın son haftasında veya yılın ilk haftasında gerçekleşecektir.
ryvantage

Yanıtlar:


94

hafta yıl ve yıl. Javadoc'dan

Haftalık bir yıl, WEEK_OF_YEAR döngüsü ile uyumludur. İlk ve son haftalar arasındaki tüm haftalar (dahil) aynı hafta yılı değerine sahiptir. Bu nedenle, bir yılın ilk ve son günleri farklı takvim yılı değerlerine sahip olabilir.

Örneğin, 1 Ocak 1998 Perşembe'dir. GetFirstDayOfWeek () PAZARTESİ ise ve getMinimalDaysInFirstWeek () 4 ise (ISO 8601 standart uyumlu ayar), 1998'in 1. haftası 29 Aralık 1997'de başlar ve 4 Ocak 1998'de biter. Hafta yılı son üç gün için 1998'dir. takvim yılının 1997. Ancak, getFirstDayOfWeek () PAZAR ise, 1998'in 1. haftası 4 Ocak 1998'de başlar ve 10 Ocak 1998'de biter; 1998'in ilk üç günü 1997'nin 53. haftasının bir parçasıdır ve hafta yılı 1997'dir.


$ date Wed Dec 30 00:42:51 UTC 2015 $ date +%G 2015 $ date +%Y 2015 Bazı yazılımlar karıştı: strftimebugün (29.12.2015) 53. hafta olarak ve 2015 olarak hafta-yıl olarak hesaplıyor.
aks

11

GregorianCalendar muhtemelen kullanımdan kaldırılacağı veya gelecekteki JDK sürümlerinden kaldırılacağı için bazı kodların bulunduğu bir Java 8 güncellemesi.

Yeni kod, WeekFieldssınıfta ve özellikle alan erişimcisi ile küçük harf y/ büyük harf için işlenir .YweekBasedYear()

Bu WeekFields temel alınarak, hafta bazlı yılın yılına erişmek için bir alan döndürür. Bu, Pazartesi gibi haftanın sabit bir gününde başladığı yıl kavramını temsil eder ve her hafta tam olarak bir yıla aittir. Bu alan genellikle dayOfWeek () ve weekOfWeekBasedYear () ile kullanılır.

Birinci hafta (1), yılda en az getMinimalDaysInFirstWeek () gününün olduğu getFirstDayOfWeek () ile başlayan haftadır. Bu nedenle, birinci hafta yılın başlangıcından önce başlayabilir. İlk hafta yılın başlangıcından sonra başlıyorsa, önceki dönem bir önceki yılın son haftasıdır.

Bu alan herhangi bir takvim sistemiyle kullanılabilir.

Ayrıştırmanın çözümleme aşamasında, hafta bazlı yıl, hafta-yıl ve haftanın gününden bir tarih oluşturulabilir.

Katı modda, üç alan da geçerli değer aralıklarına göre doğrulanır. Yılın haftası alanı, sonuçta elde edilen hafta temelli yılın, istenen hafta temelli yıl olmasını sağlamak için doğrulanır.

Akıllı modda, her üç alan da geçerli değer aralığına göre doğrulanır. Haftanın-haftası-temelli-yıl alanı 1'den 53'e kadar doğrulanır, bu da sonuç tarihinin sonraki hafta-temelli yıl içinde belirtilen tarih olabileceği anlamına gelir.

Esnek modda, yıl ve haftanın günü, geçerli değerler aralığına göre doğrulanır. Ortaya çıkan tarih, aşağıdaki üç aşamalı yaklaşıma eşdeğer olarak hesaplanır. İlk olarak, istenen hafta bazlı yılda ilk haftanın ilk gününde bir tarih oluşturun. Ardından, haftanın haftasını temel alan yılı alın, birini çıkarın ve miktarı hafta olarak tarihe ekleyin. Son olarak, yerelleştirilmiş hafta içinde haftanın doğru gününe ayarlayın.

Bu WeekFieldsörneğin kurulumu yerel ayara bağlıdır ve buna bağlı olarak farklı ayarlara sahip olabilir, Fransa gibi ABD ve Avrupa ülkeleri hafta başında farklı bir güne sahip olabilir.

Örneğin DateFormatterBuilderJava 8, ayrıştırıcıyı yerel ayarla somutlaştırın ve Ysembol için bu yerel ayarı kullanın :

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);
        }

        ...
    }

    ...
}

İşte bir örnek

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()));

Ve bir bölge ve üst kasanın konuda Y, ya komut satırı seçeneği ile oynayabilir -Duser.language=( fr, en, esvb) veya çağırma anda yerel zorlamak:

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)));

5

YTakvim hafta yılını destekliyorsa, hafta yılını almak için biçimlendirin . ( getCalendar().isWeekDateSupported())


0

Ben zor yoldan JSTL etiket kitaplığını öğrenilen format:dateile shorttalep edilen biçim yorganın altında YYYY kullanır. Bu gerçekten de basılı tarihi bir yıl öncesine çevirebilir.


0

Bir tarihi ileri geri dönüştürüyorum - bunu yaptığınızda aynı yılı beklersiniz.

Birini nasıl ilerlettiğine dikkat edin!

Bu kötü: YYYY! YYYY

Burada çalıştırabilirsiniz .

import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import static java.lang.System.out;
class Playground {
    public static Date convertYYYYMMDDStr(String s) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date result = null;
        try {
            result = sdf.parse(s);
        } catch(ParseException e) {
            e.printStackTrace();
        }
        return result;
    }
    public static String formatDateToStrWithSDF(Date d, SimpleDateFormat s) {
        return s.format(d);
    }
    public static void main(String[ ] args) {
        // DON'T DO. Use yyyy instead of YYYY
        SimpleDateFormat sdfdmy = new SimpleDateFormat("dd-MM-YYYY"); 
        String jan1st2020sb = "2020-01-01";
        Date jan1st2020d = convertYYYYMMDDStr(jan1st2020sb);
        String jan1st2020sa = formatDateToStrWithSDF(jan1st2020d, sdfdmy);
        out.println(jan1st2020sb);
        out.println(jan1st2020d);
        out.println(jan1st2020sa);
        String dec31st2020sb = "2020-12-31";
        Date dec31st2020d = convertYYYYMMDDStr(dec31st2020sb);
        String dec31st2020sa = formatDateToStrWithSDF(dec31st2020d, sdfdmy);
        out.println(dec31st2020sb);
        out.println(dec31st2020d);
        out.println(dec31st2020sa);
    }
}

Bu iyi: yyyy

yyyy

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.