Adakah anda tahu apakah perbezaan antara aksara 'Y' dan 'y' dalam corak tarikh Java? Dalam artikel ini, kami akan meneroka cara format tarikh yang salah boleh menyebabkan ralat. Kami juga akan memperkenalkan peraturan diagnostik V6122 baharu kami untuk Java yang akan menyelamatkan anda daripada perjalanan masa mengejut.
Selepas membersihkan buku nota besar TODO kami, kami terjumpa sarung yang sangat menarik. Seorang pengulas pada artikel itu menyerlahkan isu yang berpotensi.
Ulasannya
Ngomong-ngomong, inilah idea untuk anda: SimpleDateFormat di Jawa boleh menghasilkan kejutan Tahun Baru—setahun yang ditulis dalam huruf kecil tidak sama dengan tahun yang ditulis dengan huruf besar. Pada minggu terakhir tahun ini, anda mungkin tiba-tiba mendapati diri anda pada masa hadapan, kerana "YYYY" untuk tarikh 27.12.2021–31.12.2021 ialah 2022, bukan 2021 seperti yang dijangkakan sesetengah pihak.
Mari kita ke bahagian bawah ini.
Jika anda terlupa apa itu SimpleDateFormat, anda boleh menyempurnakan pengetahuan anda di sini.
Untuk menyimpan dan memaparkan tarikh, kita sering memerlukan tarikh tersebut mengikut corak tertentu. SimpleDateFormat ialah kelas yang membolehkan kami memformat tarikh dengan mudah mengikut corak yang diberikan. Selain pemformatan, SimpleDateFormat juga boleh menghuraikan rentetan dan menukarnya kepada objek tarikh.
Adakah itu sahaja yang ditawarkan oleh Java? Selain SimpleDateFormat, kelas DateTimeFormatter juga boleh memformat tarikh.
Biar saya tunjukkan kepada anda contoh penggunaan kedua-dua kelas ini.
Jika kami memformat tarikh melalui SimpleDateFormat:
public static void main(String[] args) { Date date = new Date("2024/12/31"); var dateFormatter = new SimpleDateFormat("dd-MM-yyyy"); System.out.println(dateFormatter.format(date)); }
Konsol memaparkan perkara berikut:
31-12-2024
Apa yang berlaku di sini?
Kami mempunyai tarikh dan kami mahu menyimpan/memaparkannya dalam format tertentu. Untuk mencapainya, kami mencipta objek SimpleDateFormat dengan menghantar rentetan corak kepada pembina. Tarikh diformatkan betul-betul mengikut corak ini. Kaedah format mengembalikan perwakilan rentetan tarikh yang diformatkan. Inilah yang kami mahukan.
Ini perkara yang sama, tetapi kami menggunakan DateTimeFormatter:
public static void main(String[] args) { LocalDate date = LocalDate.of(2024, 12, 31); var formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); System.out.println(formatter.format(date)); }
Konsol memaparkan perkara berikut:
31-12-2024
Langkah dan hasil yang sama, tetapi terdapat sedikit perbezaan: DateTimeFormatter membolehkan kami memformatkan hanya tarikh yang diwakili oleh kelas yang melaksanakan antara muka TemporalAccessor. Contohnya, ini termasuk LocalDate dan LocalDateTime. SimpleDateFormat memformatkan objek kelas Tarikh sahaja.
Mari kita kembali ke ulasan. Adakah penggunaan 'Y' dan bukannya 'y' dalam corak tarikh benar-benar mengubah keputusan?
Lihat kod:
public static void main(String[] args) { Date date = new Date("2024/12/31"); var dateFormatter = new SimpleDateFormat("dd-MM-yyyy"); System.out.println(dateFormatter.format(date)); }
Konsol memaparkan perkara berikut:
31-12-2025
Op. Adakah ia sama apabila ia berkaitan dengan DateTimeFormatter?
Ini kodnya:
public static void main(String[] args) { LocalDate date = LocalDate.of(2024, 12, 31); var formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); System.out.println(formatter.format(date)); }
Konsol memaparkan perkara berikut:
31-12-2025
Kami melakukan perjalanan setahun ke masa hadapan. Sudah tiba masanya untuk melihat apa yang berlaku.
Langkah pertama saya ialah melihat dokumentasi untuk kelas SimpleDateFormat. Di bawah ialah serpihan kecil jadual yang menerangkan cara corak tarikh mentafsir aksara abjad yang kami minati:
Letter | Date or Time Component | Presentation | Examples |
---|---|---|---|
y | Year | Year | 1996; 96 |
Y | Week year | Year | 2009; 09 |
Setahun seminggu? Biar saya terangkan.
Tahun minggu ialah tahun berdasarkan nombor minggu dalam tahun tersebut. Apakah maksudnya dan mengapa ia penting?
Dalam tugasan tertentu, nombor urutan minggu dalam setahun adalah penting. Untuk menentukan nombor urutan minggu, kita perlu memutuskan minggu mana yang perlu dipertimbangkan terlebih dahulu. Ini kerana peralihan dari satu tahun ke tahun yang lain selalunya menyebabkan beberapa minggu melangkaui kedua-dua tahun. Jadi, bagaimana kita boleh tahu tahun mana minggu ini? Piawaian ISO-8601 mengawal selia ini.
Mengikut piawaian ini, minggu pertama dalam tahun mesti memenuhi syarat berikut:
Daripada ini, kita boleh menyimpulkan peraturan mudah: seminggu dianggap sebagai yang pertama dalam tahun jika Khamis jatuh pada bulan Januari.
Contoh kehidupan sebenar boleh menjelaskan perkara ini dengan lebih lanjut.
Mari kita ambil tarikh dari contoh, iaitu 31.12.2024. Di bawah ialah coretan kalendar untuk minggu yang termasuk tarikh kami (Disember 2024–Januari 2025):
Mo | Tu | We | Th | Fr | Sa | Su |
---|---|---|---|---|---|---|
30 | 31 | 1 | 2 | 3 | 4 | 5 |
Minggu ini dianggap minggu pertama 2025 kerana ia memenuhi syarat di atas (ia mempunyai lima hari Januari). Jadi, jika kita menggunakan penentu 'Y', kita mendapat tahun 2025.
Seperti yang anda boleh teka, kes dengan DateTimeFormatter adalah sama.
Adalah penting untuk ambil perhatian bahawa kita boleh mengembara bukan sahaja ke masa depan tetapi juga ke masa lalu.
Jom temu janji lagi, 01.01.2027.
Adakah minggu pertama 2027 termasuk 1 Januari? Sekali lagi, mari rujuk kalendar.
Di bawah ialah coretan kalendar untuk minggu yang merangkumi tarikh kami (Disember 2026–Januari 2027):
Mo | Tu | We | Th | Fr | Sa | Su |
---|---|---|---|---|---|---|
28 | 29 | 30 | 31 | 1 | 2 | 3 |
Memandangkan hanya ada tiga hari Januari dalam minggu ini (dan sepatutnya empat hari dalam minggu pertama mengikut keperluan), ia dikira sebagai minggu terakhir 2026. Jadi, tarikh, apabila diformat menggunakan 'Y' watak, akan menunjukkan kepada kita 2026.
Ini buktinya. Tengok kod:
public static void main(String[] args) { Date date = new Date("2024/12/31"); var dateFormatter = new SimpleDateFormat("dd-MM-yyyy"); System.out.println(dateFormatter.format(date)); }
Konsol memaparkan perkara berikut:
01-01-2026
Baiklah, kami telah membedah isu ini. Kami juga mendapati ia cukup menarik untuk menambahkan peraturan diagnostik khusus pada penganalisis Java PVS-Studio.
Peraturan diagnostik telah ditulis, jadi sudah tiba masanya untuk mengujinya.
Semasa pembangunan penganalisis, salah satu peringkat ujian melibatkan menjalankan ujian regresi. Kami mempunyai artikel tentang proses ini. Ringkasnya, apabila kami menambah peraturan diagnostik baharu, kami menganalisis sekumpulan besar projek sumber terbuka dan membandingkan laporan baharu dengan laporan rujukan.
Dalam kes peraturan diagnostik ini, penganalisis mengeluarkan amaran baharu untuk beberapa projek. Mari lihat mereka.
Dalam projek ini, serpihan kod yang ditunjukkan oleh peraturan diagnostik adalah sama, jadi saya akan tunjukkan hanya satu daripadanya.
Lihat kod:
public static void main(String[] args) { LocalDate date = LocalDate.of(2024, 12, 31); var formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); System.out.println(formatter.format(date)); }
Amaran PVS-Studio:
V6122 Penggunaan corak 'Y' (tahun minggu) telah dikesan: ia mungkin bertujuan untuk menggunakan 'y' (tahun). SkeinParameters.java 246
Mula-mula, saya melihat GitHub. Bagaimana jika ia benar-benar pepijat, pembangun telah menemuinya dan melakukan pembetulan? Itulah yang berlaku. Berikut ialah pautan ke komit, anda boleh menyemaknya. Semua aksara 'Y' (tahun minggu) kami dalam corak telah digantikan dengan 'y' (tahun).
Anda mungkin tertanya-tanya mengapa komitmen dibuat agak lama dahulu. Biar saya terangkan. Ujian regresi kami tidak bertujuan untuk terus mengawal kualiti projek sumber terbuka ini atau itu. Tugasnya adalah untuk melihat bagaimana laporan berubah apabila peraturan diagnostik baharu ditambahkan: tiada amaran lama akan hilang, tiada ralat baharu akan muncul, kerana itu akan menunjukkan bahawa penganalisis mempunyai masalah. Jadi, kod yang disemak mestilah sama.
Sekarang mari kita lihat projek kedua di mana peraturan diagnostik dicetuskan.
Amaran PVS-Studio:
V6122 Penggunaan corak 'Y' (tahun minggu) telah dikesan: ia mungkin bertujuan untuk menggunakan 'y' (tahun). RepositoryInfo.java 77
Kod:
public static void main(String[] args) { Date date = new Date("2024/12/31"); var dateFormatter = new SimpleDateFormat("dd-MM-YYYY"); System.out.println(dateFormatter.format(date)); }
Sama seperti projek sebelumnya, saya bergegas ke komit untuk melihat apa yang sedang berlaku. Pertama sekali, perlu diingat bahawa medan itu berpindah ke kelas terbitannya, Repositori, hasil daripada pemfaktoran semula (inilah pautan ke komit). Saya mencari lebih jauh dan menemui komit yang mengandungi pembetulan. Aksara 'Y' dalam corak tarikh telah digantikan dengan 'y':
public static void main(String[] args) { LocalDate date = LocalDate.of(2024, 12, 31); var formatter = DateTimeFormatter.ofPattern("dd-MM-YYYY"); System.out.println(formatter.format(date)); }
Jadi, ralat di sini juga.
Di PVS-Studio, kami mengalu-alukan sebarang maklum balas daripada komuniti. Selepas menangani ulasan daripada pengguna Habr, kami telah mempertingkatkan penganalisis Java dengan menambahkan beberapa peraturan diagnostik yang berguna. Jadi, jika anda mempunyai sebarang pendapat yang ingin anda kongsikan dengan kami, kami ingin berbual dengan anda di bahagian komen artikel ini.
Dengan cara ini, peraturan diagnostik telah diperkenalkan pada keluaran 7.33 Oktober. Jadi, jika anda ingin mencuba penganalisis kami, gunakan pautan ini.
Itu sahaja. Mari kita selesaikan perkara di sini. Mudah-mudahan, perjalanan mengejut setahun ke hadapan (atau ke belakang) tidak akan mengejutkan anda.
Atas ialah kandungan terperinci YYYY? yyyy!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!