Panduan untuk SimpleDateFormat

1. Pengenalan

Dalam tutorial ini, kita akan mengikuti lawatan mendalam kelas SimpleDateFormat .

Kami akan melihat gaya instansiasi dan pemformatan yang sederhana serta kaedah berguna yang didedahkan oleh kelas untuk menangani tempat dan zon waktu .

2. Instansiasi ringkas

Pertama, mari kita lihat cara membuat objek SimpleDateFormat baru .

Terdapat 4 kemungkinan pembina - tetapi sesuai dengan namanya, mari kita memperbaikinya. Yang perlu kita mulakan hanyalah rentetan dari corak tarikh yang kita mahukan .

Mari mulakan dengan corak tarikh yang dipisahkan dengan tanda hubung seperti:

"dd-MM-yyyy"

Ini akan memformat tarikh dengan betul bermula dengan hari semasa bulan ini, bulan semasa tahun ini, dan akhirnya tahun semasa. Kita boleh menguji pemformat baru kita dengan ujian unit mudah. Kami akan membuat objek SimpleDateFormat baru , dan meneruskan tarikh yang diketahui:

SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy"); assertEquals("24-05-1977", formatter.format(new Date(233345223232L))); 

Dalam kod di atas, Pemformat saudara milisaat sebagai l ong ke suatu tarikh yang boleh dibaca manusia - yang 24 Mei 1977.

2.1. Kaedah Kilang

Walaupun SimpleDateFormat adalah kelas berguna untuk cepat membina tarikh yang Pemformat, kita digalakkan untuk menggunakan kaedah kilang di dateformat kelas getDateFormat () , getDateTimeFormat () , getTimeFormat () .

Contoh di atas kelihatan sedikit berbeza ketika menggunakan kaedah kilang ini:

DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT); assertEquals("5/24/77", formatter.format(new Date(233345223232L)));

Seperti yang dapat kita ketahui dari atas, bilangan pilihan pemformatan ditentukan terlebih dahulu oleh bidang pada kelas DateFormat . Ini sebahagian besarnya menyekat pilihan kami untuk memformat dan itulah sebabnya kami akan berpegang pada SimpleDateFormat dalam artikel ini.

2.2. Keselamatan Benang

JavaDoc untuk SimpleDateFormat secara eksplisit menyatakan:

Format tarikh tidak diselaraskan. Adalah disyorkan untuk membuat contoh format yang berasingan untuk setiap utas. Sekiranya beberapa utas mengakses format secara serentak, ia mesti diselaraskan secara luaran.

Oleh itu, contoh SimpleDateFormat tidak selamat di dalam benang , dan kita harus menggunakannya dengan berhati-hati dalam persekitaran serentak.

Pendekatan terbaik untuk menyelesaikan masalah iniadalah menggunakannya dalam kombinasi dengan ThreadLocal . Dengan cara ini, setiap utas berakhir dengan contoh SimpleDateFormat sendiri , dan kekurangan perkongsian menjadikan program ini selamat:

private final ThreadLocal formatter = ThreadLocal .withInitial(() -> new SimpleDateFormat("dd-MM-yyyy"));

Argumen untuk kaedah withInitial adalah pembekal contoh SimpleDateFormat . Setiap kali ThreadLocal perlu membuat instance, ia akan menggunakan pembekal ini.

Kemudian kita boleh menggunakan formatter melalui contoh ThreadLocal :

formatter.get().format(date)

Kaedah ThreadLocal.get () memulakan SimpleDateFormat untuk utas semasa pada mulanya dan kemudian menggunakan semula contoh itu.

Kami memanggil teknik ini sebagai pengikat benang kerana kami mengehadkan penggunaan setiap contoh kepada satu utas tertentu.

Terdapat dua pendekatan lain untuk mengatasi masalah yang sama:

  • Menggunakan blok yang disegerakkan atau ReentrantLock s
  • Membuat contoh membuang SimpleDateFormat atas permintaan

Kedua-dua pendekatan ini tidak disarankan: Yang pertama mengalami prestasi yang sangat tinggi ketika perselisihan tinggi, dan yang terakhir membuat banyak objek, memberi tekanan pada pengumpulan sampah.

Perlu disebutkan bahawa, sejak Java 8, kelas DateTimeFormatter baru telah diperkenalkan . Kelas DateTimeFormatter yang baru tidak berubah dan selamat di dalam benang. Sekiranya kita bekerja dengan Java 8 atau lebih baru , disyorkan menggunakan kelas DateTimeFormatter yang baru .

3. Menghuraikan Tarikh

SimpleDateFormat dan dateformat bukan sahaja membolehkan kita untuk tarikh format - tetapi kita juga boleh mengembalikan operasi. Dengan menggunakan kaedah parse , kita dapat memasukkan representasi String tarikh dan mengembalikan bersamaan objek Date :

SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy"); Date myDate = new Date(233276400000L); Date parsedDate = formatter.parse("24-05-1977"); assertEquals(myDate.getTime(), parsedDate.getTime());

Penting untuk diperhatikan di sini bahawa corak yang diberikan dalam konstruktor harus dalam format yang sama dengan tarikh yang dihuraikan menggunakan kaedah parse .

4. Corak Tarikh-Masa

SimpleDateFormat menyediakan pelbagai pilihan yang berbeza semasa memformat tarikh. Walaupun senarai lengkap tersedia di JavaDocs, mari kita meneroka beberapa pilihan yang paling biasa digunakan:

Surat Komponen Tarikh Contohnya
M Sebulan 12; Dis
y tahun 94
d hari 23; Isnin
H jam 03
m minit 57

The output dikembalikan oleh komponen tarikh juga bergantung sepenuhnya kepada bilangan aksara yang digunakan dalam tali . Sebagai contoh, mari kita ambil bulan Jun. Sekiranya kita menentukan rentetan tarikh sebagai:

"MM"

Kemudian hasil kami akan muncul sebagai kod nombor - 06. Walau bagaimanapun, jika kami menambahkan M lain pada rentetan tarikh kami:

"MMM"

Kemudian tarikh berformat yang dihasilkan kami muncul sebagai perkataan Jun .

5. Mengaplikasi Lokasi

The SimpleDateFormat kelas juga menyokong pelbagai pilihan yang ditetapkan apabila pembina dipanggil.

Mari kita praktikkan ini dengan memformat tarikh dalam bahasa Perancis. Kami akan membuat objek SimpleDateFormat semasa membekalkan Locale.FRANCE kepada pembina.

SimpleDateFormat franceDateFormatter = new SimpleDateFormat("EEEEE dd-MMMMMMM-yyyy", Locale.FRANCE); Date myWednesday = new Date(1539341312904L); assertTrue(franceDateFormatter.format(myWednesday).startsWith("vendredi"));

Dengan memberikan tarikh tertentu, pada hari Rabu petang, kami dapat menegaskan bahawa franceDateFormatter kami telah memformat tarikh dengan betul. Tarikh baru dengan betul bermula dengan Vendredi -Farench untuk hari Rabu!

Perlu diperhatikan sedikit getcha dalam versi konstruktor Locale - sementara banyak tempat disokong, liputan penuh tidak dijamin . Oracle mengesyorkan menggunakan kaedah kilang pada kelas DateFormat untuk memastikan liputan setempat.

6. Menukar Zon Waktu

Sejak SimpleDateFormat memanjangkan dateformat kelas, kita juga boleh memanipulasi zon masa menggunakan setTimeZone kaedah . Mari lihat ini dalam tindakan:

Date now = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEEE dd-MMM-yy HH:mm:ssZ"); simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Europe/London")); logger.info(simpleDateFormat.format(now)); simpleDateFormat.setTimeZone(TimeZone.getTimeZone("America/New_York")); logger.info(simpleDateFormat.format(now));

In the above example, we supply the same Date to two different time zones on the same SimpleDateFormat object. We've also added the ‘Z' character to the end of the pattern String to indicate the time zone differences. The output from the format method is then logged for the user.

Hitting run, we can see the current times relative to the two time zones:

INFO: Friday 12-Oct-18 12:46:14+0100 INFO: Friday 12-Oct-18 07:46:14-0400

7. Summary

In this tutorial, we've taken a deep dive into the intricacies of SimpleDateFormat.

We've looked at how to instantiate SimpleDateFormat as well as how the pattern String impacts how the date is formatted.

Kami bermain-main dengan mengubah lokasi output String sebelum akhirnya bereksperimen dengan menggunakan zon waktu .

Seperti biasa kod sumber lengkap boleh didapati di GitHub.