我想知道为什么'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
任何人都可以解释原因吗?
答案 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=
(fr
,en
,{{1} },等等,或在调用时强制语言环境:
es
答案 2 :(得分:5)
格式Y
以获取日历支持周年的周年。 (getCalendar().isWeekDateSupported()
)
答案 3 :(得分:1)
我学习了JSTL标记库format:date
与short
作为请求格式的困难方式,使用了YYYY。这确实可以在一年之前推出印刷日期。
答案 4 :(得分:0)
我来回转换日期-执行此操作时,您希望与之相同。
注意它如何前进!
您可以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