Y返回2012,而y在SimpleDateFormat中返回2011

时间:2011-12-31 04:40:49

标签: java date simpledateformat

我想知道为什么'Y'会返回2012,而'y'会在SimpleDateFormat中返回2011年:

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

任何人都可以解释原因吗?

5 个答案:

答案 0 :(得分:74)

week year和一年。来自javadoc

  

周年与WEEK_OF_YEAR周期同步。几周之间   第一周和最后一周(包括)具有相同的周年值。   因此,一周的第一天和最后一天可能会有所不同   历年值。

     

例如,1998年1月1日是星期四。如果getFirstDayOfWeek()是   星期一和getMinimalDaysInFirstWeek()是4(ISO 8601标准   兼容设定),1998年第1周开始于1997年12月29日,   并于1998年1月4日结束。最后三年的一周是1998年   1997年的日历年。但是,如果是getFirstDayOfWeek()   1998年1月4日星期日,1998年1月1日开始,结束   1998年1月10日; 1998年的前三天是一周的一部分   1997年第53号,其一周是1997年。

答案 1 :(得分:11)

这里是带有一些代码的Java 8更新,因为GregorianCalendar可能会被弃用或从未来的JDK版本中删除。

新代码在WeekFields类中处理,特别是针对带有weekBasedYear()字段访问者的小写y /大写Y

  

返回一个字段,以便根据此字段访问基于周的年份   WeekFields。这代表了几周开始的一年的概念   在固定的星期几,如星期一和每周属于   整整一年。此字段通常与dayOfWeek()和。一起使用   weekOfWeekBasedYear()。

     

第一周(1)是从getFirstDayOfWeek()开始的那一周   一年中至少有getMinimalDaysInFirstWeek()天。的因此,   第一周可能在年初之前开始。如果是第一周   在年初之后开始,然后是之前的时期   去年的最后一周。

     

此字段可用于任何日历系统。

     

在解析的解析阶段,可以从a创建日期   以工作周为基础的年份,周年和星期几。

     

在严格模式下,所有三个字段都根据其范围进行验证   有效值。验证了每周的字段以确保该字段   由此产生的基于周的年份是要求的以周为基础的年份。

     

在智能模式下,所有三个字段都根据其范围进行验证   有效值。基于周周的字段从1到1进行验证   53,意味着得到的日期可以在下面   基于周的年份到指定的年份。

     

在宽松模式下,年份和星期几经过验证   有效值范围。结果日期的计算等价于   以下三个阶段的方法。首先,在第一个上创建一个日期   请求的基于周的年份的第一周的一天。然后拿走   以周为基础的年份,减1,并在几周内添加金额   日期。最后,调整到正确的星期几   本地化的一周。

WeekFields实例的设置取决于区域设置,可能会有不同的设置,美国和欧洲国家(如法国)可能会有不同的一天作为一周的开始。

例如Java 8的DateFormatterBuilder,使用语言环境实例化解析器,并将此语言环境用于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);
        }

        ...
    }

    ...
}

这里有一些例子

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

关于区域设置和大写Y,您可以使用命令行选项-Duser.language=fren,{{1} },等等,或在调用时强制语言环境:

es

答案 2 :(得分:5)

格式Y以获取日历支持周年的周年。 (getCalendar().isWeekDateSupported()

答案 3 :(得分:1)

我学习了JSTL标记库format:dateshort作为请求格式的困难方式,使用了YYYY。这确实可以在一年之前推出印刷日期。

答案 4 :(得分:0)

我来回转换日期-执行此操作时,您希望与之相同。

注意它如何前进!

这很糟糕:YYYY! YYYY

您可以here运行它。

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

这很好:yyyy

yyyy