왜 'Y'가 2012를 반환하고 'y'가 2011을 반환하는지 궁금합니다 SimpleDateFormat
.
System.out.println(new SimpleDateFormat("Y").format(new Date())); // prints 2012
System.out.println(new SimpleDateFormat("y").format(new Date())); // prints 2011
아무도 이유를 설명 할 수 있습니까?
왜 'Y'가 2012를 반환하고 'y'가 2011을 반환하는지 궁금합니다 SimpleDateFormat
.
System.out.println(new SimpleDateFormat("Y").format(new Date())); // prints 2012
System.out.println(new SimpleDateFormat("y").format(new Date())); // prints 2011
아무도 이유를 설명 할 수 있습니까?
답변:
주 연도 . javadoc에서
1 주일은 WEEK_OF_YEAR주기와 동기화됩니다. 첫 주와 마지막 주 (포함) 사이의 모든 주에는 동일한 주 연도 값이 있습니다. 따라서 한주의 첫 번째 날과 마지막 날은 다른 역년 값을 가질 수 있습니다.
예를 들어 1998 년 1 월 1 일은 목요일입니다. getFirstDayOfWeek ()가 MONDAY이고 getMinimalDaysInFirstWeek ()가 4 (ISO 8601 표준 호환 설정)이면 1998 년의 1주는 1997 년 12 월 29 일에 시작하여 1998 년 1 월 4 일에 끝납니다. 주 연도는 지난 3 일 동안 1998 년입니다. 그러나 getFirstDayOfWeek ()가 SUNDAY이면 1998 년 1 주차는 1998 년 1 월 4 일에 시작하여 1998 년 1 월 10 일에 끝납니다. 1998 년의 처음 3 일은 1997 년 53 주차의 일부이며 주연도는 1997 년입니다.
$ date Wed Dec 30 00:42:51 UTC 2015
$ date +%G 2015
$ date +%Y 2015
일부 소프트웨어는 혼란 스럽습니다. strftime
오늘 (2015 년
GregorianCalendar는 향후 JDK 버전에서 더 이상 사용되지 않거나 제거 될 것이므로 일부 코드가 포함 된 Java 8 업데이트가 있습니다.
새 코드는 WeekFields
클래스 에서 처리되며 특히 필드 접근자가 있는 소문자 y
/ 대문자에 대해 처리됩니다 .Y
weekBasedYear()
이 WeekFields를 기반으로 한 주 기반 연도의 연도에 액세스하는 필드를 반환합니다. 이것은 주가 월요일과 같이 고정 된 요일에 시작되고 각 주가 정확히 1 년에 속하는 연도의 개념을 나타냅니다. 이 필드는 일반적으로 dayOfWeek () 및 weekOfWeekBasedYear ()와 함께 사용됩니다.
1 주차는 1 년에 최소한 getMinimalDaysInFirstWeek () 일이있는 getFirstDayOfWeek ()에 시작하는 주입니다. 따라서 1 주차는 연도가 시작되기 전에 시작될 수 있습니다. 첫 번째 주가 연도가 시작된 후 시작되는 경우 이전 기간은 전년도의 마지막 주입니다.
이 필드는 모든 달력 시스템에서 사용할 수 있습니다.
구문 분석의 해결 단계에서 주 기반 연도, 주 및 요일로 날짜를 만들 수 있습니다.
엄격 모드에서는 세 필드 모두 유효한 값 범위에 대해 유효성이 검사됩니다. 주 단위 필드는 결과 주 단위 연도가 요청 된 주 단위 연도인지 확인하기 위해 유효성이 검사됩니다.
스마트 모드에서는 세 필드 모두 유효한 값 범위에 대해 유효성이 검사됩니다. 주 기준 연도 필드는 1부터 53까지의 유효성을 검사합니다. 즉, 결과 날짜는 지정된 연도의 다음 주 기준 연도 일 수 있습니다.
관대 모드에서는 유효한 값 범위에 대해 연도와 요일의 유효성이 검사됩니다. 결과 날짜는 다음 3 단계 접근 방식과 동일하게 계산됩니다. 먼저 요청 된 주 기반 연도의 첫 번째주의 첫 번째 날에 날짜를 만듭니다. 그런 다음 주 단위 연도를 가져 와서 1을 빼고 날짜에 주 단위의 금액을 더합니다. 마지막으로 현지화 된 주 내에서 올바른 요일로 조정합니다.
이것의 설정 WeekFields
인스턴스 로케일에 따라 다르며 이에 따라 설정이 다를 수 있으며, 미국 및 프랑스와 같은 유럽 국가에서는 요일이 요일로 다를 수 있습니다.
예를 들어 DateFormatterBuilder
Java 8의 경우 로케일로 구문 분석기를 인스턴스화하고 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
, 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)));
날짜를 앞뒤로 변환합니다. 이렇게하면 같은 해를 예상 할 수 있습니다.
그것이 어떻게 발전하는지 주목하십시오!
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