Java Y以SimpleDateFormat返回2012,而Y以SimpleDateFormat返回2011
我想知道为什么“Y”返回2012而“Y”在Java Y以SimpleDateFormat返回2012,而Y以SimpleDateFormat返回2011,java,date,simpledateformat,Java,Date,Simpledateformat,我想知道为什么“Y”返回2012而“Y”在SimpleDataFormat中返回2011: System.out.println(new SimpleDateFormat("Y").format(new Date())); // prints 2012 System.out.println(new SimpleDateFormat("y").format(new Date())); // prints 2011 有人能解释为什么吗?和年份。来自javadoc 一周一年与一周一年的周期同步。两周
SimpleDataFormat
中返回2011:
System.out.println(new SimpleDateFormat("Y").format(new Date())); // prints 2012
System.out.println(new SimpleDateFormat("y").format(new Date())); // prints 2011
有人能解释为什么吗?和年份。来自javadoc
一周一年与一周一年的周期同步。两周之间
第一周和最后一周(含)具有相同的周-年值。
因此,一年中一周的第一天和最后几天可能会有不同的结果
日历年值。
例如,1998年1月1日是星期四。如果getFirstDayOfWeek()为
星期一和getMinimalDaysInFirstWeek()为4(ISO 8601标准
然后1998年第1周从1997年12月29日开始,
并于一九九八年一月四日结束。过去三年的一周是1998年
1997日历年的天数。但是,如果getFirstDayOfWeek()是
星期日,然后是1998年第1周,开始于1998年1月4日,结束于
一九九八年一月十日;;1998年的前三天是一周的一部分
1997年的第53周,他们的周年是1997年
格式化
Y
以获取周年(如果日历支持周年)。(getCalendar().isWeekDateSupported()
)我用short
艰难地学习了JSTL标记库格式:date
,因为请求的格式在封面下使用YYYY。这确实可以将打印日期提前一年。这里有一个Java 8更新,其中包含一些代码,因为GregoriaCalendar可能会被弃用或从未来的JDK版本中删除
新代码在WeekFields
类中处理,特别是对于小写y
/大写y
,使用字段访问器
返回一个字段,以便根据此字段访问基于周的年份
WeekFields。这代表了一年中周开始的概念
在一周中的固定日期,如星期一和每周属于
整整一年。此字段通常与dayOfWeek()和
weekOfWeekBasedYear()
第一周(1)是从getFirstDayOfWeek()开始的一周,其中
一年中至少有getMinimalDaysInFirstWeek()天因此,
第一周可以在年初之前开始。如果第一周
在年初之后开始,之前的期间在
上一年的最后一周。
此字段可用于任何日历系统
在解析的解析阶段,可以从
基于周的年、年中的周和周中的天
在严格模式下,所有三个字段都根据其范围进行验证
有效值。验证“年度周”字段,以确保
生成的基于周的年是请求的基于周的年
在智能模式下,所有三个字段都根据其范围进行验证
有效值。基于周的年字段的有效期从1到
53,这意味着结果日期可以是
指定年份的周数
在宽松模式下,根据
有效值的范围。计算得出的日期等于
以下三个阶段的方法。首先,在第一天创建一个日期
请求的基于周的年份中第一周的日期。那就乘火车吧
基于年份的周数,减去一,然后将周数相加到
日期。最后,调整到一周中正确的一天
本地化周
此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);
}
...
}
...
}
关于区域设置和大写字母Y
,您可以使用命令行选项-Duser.language=
(fr
,en
,es
,等等),或者在调用时强制使用区域设置:
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)));
我来回转换一个日期——当你这样做的时候,你会期待同一年 注意它是如何进步的 这很糟糕:YYYY! 你可以运行它 这是好的:yyyy
作为对未来读者的提醒:这种行为只会发生在一年的最后一周或一年的第一周。
$date Wed Dec 30 00:42:51 UTC 2015
$date+%G 2015
$date+%Y 2015
一些软件感到困惑:strftime
将今天(12/29/2015)计算为第53周,2015年为一周。
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)));
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);
}
}