Y ส่งคืน 2012 ในขณะที่ y ส่งคืน 2011 ใน SimpleDateFormat


85

ฉันสงสัยว่าทำไม '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

มีใครอธิบายได้ไหมว่าทำไม?


40
เช่นเดียวกับผู้อ่านในอนาคต: พฤติกรรมนี้จะเกิดขึ้นในช่วงสัปดาห์สุดท้ายของปีหรือสัปดาห์แรกของปีเท่านั้น
ryvantage

คำตอบ:


94

สัปดาห์ปีและปี จาก javadoc

ปีหนึ่งสัปดาห์จะซิงค์กับวัฏจักร WEEK_OF_YEAR สัปดาห์ทั้งหมดระหว่างสัปดาห์แรกและสัปดาห์สุดท้าย (รวม) มีค่าปีของสัปดาห์เดียวกัน ดังนั้นวันแรกและวันสุดท้ายของสัปดาห์ปีอาจมีค่าปีปฏิทินต่างกัน

ตัวอย่างเช่นวันที่ 1 มกราคม 1998 เป็นวันพฤหัสบดี ถ้า getFirstDayOfWeek () เป็นวันจันทร์และ getMinimalDaysInFirstWeek () คือ 4 (การตั้งค่าที่เข้ากันได้กับมาตรฐาน ISO 8601) สัปดาห์ที่ 1 ของปี 1998 จะเริ่มในวันที่ 29 ธันวาคม 1997 และสิ้นสุดในวันที่ 4 มกราคม 1998 ปีของสัปดาห์คือ 1998 ในช่วงสามวันที่ผ่านมา ของปีปฏิทิน 1997 อย่างไรก็ตามถ้า getFirstDayOfWeek () เป็นวันอาทิตย์สัปดาห์ที่ 1 ของปี 1998 จะเริ่มในวันที่ 4 มกราคม 1998 และสิ้นสุดในวันที่ 10 มกราคม 1998 สามวันแรกของปี 1998 เป็นส่วนหนึ่งของสัปดาห์ที่ 53 ของปี 1997 และปีของสัปดาห์คือ 1997


$ date Wed Dec 30 00:42:51 UTC 2015 $ date +%G 2015 $ date +%Y 2015 ซอฟต์แวร์บางตัวสับสน: strftimeคำนวณวันนี้ (
aks

11

นี่คือการอัปเดต Java 8 พร้อมรหัสบางส่วนเนื่องจาก GregorianCalendar อาจถูกเลิกใช้หรือลบออกจากเวอร์ชัน JDK ในอนาคต

รหัสใหม่ได้รับการจัดการในWeekFieldsคลาสและโดยเฉพาะสำหรับตัวพิมพ์เล็กy/ ตัวพิมพ์ใหญ่Yด้วยตัวเข้าถึงweekBasedYear()ฟิลด์

ส่งคืนเขตข้อมูลเพื่อเข้าถึงปีของปีที่อิงตามสัปดาห์ตาม WeekFields นี้ นี่แสดงถึงแนวคิดของปีที่สัปดาห์เริ่มต้นในวันของสัปดาห์ที่กำหนดเช่นวันจันทร์และแต่ละสัปดาห์เป็นของหนึ่งปี โดยทั่วไปฟิลด์นี้จะใช้กับ dayOfWeek () และ weekOfWeekBasedYear ()

สัปดาห์ที่หนึ่ง (1) คือสัปดาห์ที่เริ่มต้นใน getFirstDayOfWeek () ซึ่งมีอย่างน้อย getMinimalDaysInFirstWeek () วันในปีนั้น ดังนั้นสัปดาห์ที่หนึ่งอาจเริ่มก่อนต้นปี หากสัปดาห์แรกเริ่มต้นหลังจากต้นปีระยะเวลาก่อนหน้าจะอยู่ในสัปดาห์สุดท้ายของปีก่อนหน้า

ฟิลด์นี้สามารถใช้กับระบบปฏิทินใดก็ได้

ในขั้นตอนการแก้ไขปัญหาของการแยกวิเคราะห์สามารถสร้างวันที่จากสัปดาห์ตามปีสัปดาห์ของปีและวันในสัปดาห์

ในโหมดเข้มงวดช่องทั้งสามจะได้รับการตรวจสอบความถูกต้องตามช่วงของค่าที่ถูกต้อง ช่องสัปดาห์ของปีได้รับการตรวจสอบเพื่อให้แน่ใจว่าปีที่อิงตามสัปดาห์ที่เป็นผลลัพธ์เป็นปีที่ขอตามสัปดาห์

ในโหมดสมาร์ทฟิลด์ทั้งสามช่องจะถูกตรวจสอบเทียบกับช่วงของค่าที่ถูกต้อง ช่องสัปดาห์ตามสัปดาห์มีการตรวจสอบความถูกต้องตั้งแต่ 1 ถึง 53 ซึ่งหมายความว่าวันที่ผลลัพธ์อาจอยู่ในปีที่อิงตามสัปดาห์ถัดไปตามที่ระบุไว้

ในโหมดผ่อนปรนปีและวันในสัปดาห์จะถูกตรวจสอบเทียบกับช่วงของค่าที่ถูกต้อง วันที่ที่เป็นผลลัพธ์จะถูกคำนวณเทียบเท่ากับแนวทางสามขั้นตอนต่อไปนี้ ขั้นแรกให้สร้างวันที่ในวันแรกของสัปดาห์แรกในปีตามสัปดาห์ที่ขอ จากนั้นใช้สัปดาห์ของสัปดาห์ตามปีลบหนึ่งและเพิ่มจำนวนเป็นสัปดาห์ในวันที่ สุดท้ายให้ปรับเปลี่ยนวันในสัปดาห์ที่ถูกต้องภายในสัปดาห์ที่แปล

การตั้งค่าWeekFieldsอินสแตนซ์นี้ขึ้นอยู่กับสถานที่และอาจมีการตั้งค่าที่แตกต่างกันขึ้นอยู่กับประเทศในสหรัฐอเมริกาและยุโรปเช่นฝรั่งเศสอาจมีวันที่แตกต่างกันเมื่อเริ่มต้นสัปดาห์

ตัวอย่างเช่นDateFormatterBuilderJava 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)));

5

รูปแบบYเพื่อรับปีของสัปดาห์หากปฏิทินรองรับสัปดาห์ปี ( getCalendar().isWeekDateSupported())


0

ฉันได้เรียนรู้วิธีที่ยากลำบากที่ไลบรารีแท็ก JSTL format:dateด้วยshortเนื่องจากรูปแบบที่ร้องขอใช้ YYYY ภายใต้หน้าปก ซึ่งแน่นอนสามารถม้วนวันที่พิมพ์ล่วงหน้าหนึ่งปี


0

ฉันแปลงวันที่กลับไปกลับมา - คุณคาดว่าจะเป็นปีเดียวกันเมื่อคุณทำสิ่งนี้

สังเกตว่ามันก้าวหน้าแค่ไหน!

แย่แล้ว: ปปปป! ปปปปปป

คุณสามารถเรียกใช้มันนี่

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

ปปปป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.