Untuk mengubah tanggal publikasi dan zona waktu bernama menjadi waktu tengah malam yang tepat, tentukan waktu lokal 00:00:00 menggunakan aturan zona tersebut, periksa apakah waktu itu ada, lalu konversikan ke UTC. Alur kerja Terminal Mac ini juga mendeteksi tengah malam yang berulang.

Misalkan sebuah catatan publikasi sintetis berisi tanggal 2025-07-15 dan zona America/New_York. Tugas Anda adalah menghitung stempel waktu yang mewakili tengah malam pada awal tanggal tersebut. Alur kerja di bawah ini menghasilkan stempel waktu yang dapat Anda salin ke alat yang menerima UTC, sambil tetap menampilkan tanggal dan zona asli untuk diperiksa.

Informasi apa yang menentukan waktu tengah malam?

Pisahkan keempat nilai ini sepanjang perhitungan:

Nilai Contoh sintetis Arti
Tanggal sipil 2025-07-15 Tanggal kalender Gregorian tanpa waktu atau zona
Tanggal dan waktu lokal 2025-07-15T00:00:00 Waktu yang ditunjukkan oleh jam dinding yang diminta
Zona waktu bernama America/New_York Aturan untuk menafsirkan waktu lokal tersebut
Waktu yang ditentukan 2025-07-15T04:00:00Z Satu momen tertentu yang dinyatakan dalam UTC

Python merepresentasikan tanggal kalender dengan date, menggabungkan kolom tanggal dan waktu dengan datetime, serta menggunakan informasi zona waktu untuk menafsirkan objek datetime yang sadar zona. Kelas timezone merepresentasikan offset tetap; zoneinfo menyediakan aturan zona bernama. Lihat dokumentasi datetime dan dokumentasi zoneinfo resmi.

Offset seperti -04:00 adalah selisih antara waktu lokal dan UTC untuk pembacaan waktu tertentu. Zona bernama menyediakan aturan yang dapat menghasilkan offset berbeda pada tanggal berbeda. RFC 9557 menjelaskan mengapa mengganti zona bernama dengan offset tetap dapat menghasilkan perhitungan lanjutan yang keliru. Pertahankan nama zona, alih-alih menyalin offset dari catatan publikasi lain. RFC 9557: Tanggal dan Waktu di Internet: Stempel Waktu dengan Informasi Tambahan

Untuk tugas ini, “tengah malam” berarti tepat 00:00:00 pada awal tanggal yang diberikan. Nyatakan persyaratan itu dengan jelas sebelum menghitung apa pun: permintaan untuk momen valid pertama suatu hari kalender memerlukan kebijakan berbeda jika tengah malam tidak ada.

Mengapa tengah malam harus diperiksa sebelum konversi?

Perubahan jam lokal dapat menimbulkan celah, yaitu waktu pada jam dinding yang tidak terjadi, atau lipatan, yaitu waktu yang terjadi dua kali. PEP 495 Python mendefinisikan kasus-kasus ini dan menyediakan atribut fold untuk membedakan pembacaan waktu yang berulang. PEP tersebut juga mendokumentasikan bahwa konstruktor dan replace() tidak otomatis menolak waktu lokal yang tidak ada. Karena itu, menambahkan zona saja tidak memvalidasi tengah malam yang diminta. PEP 495 – Disambiguasi Waktu Lokal

Gunakan aturan keputusan berikut untuk persyaratan publikasi yang mengharuskan tepat tengah malam:

Jumlah waktu tengah malam valid yang ditemukan Interpretasi Tindakan
Satu Tengah malam unik Kembalikan waktu tersebut
Dua Tengah malam berulang Tolak sampai kebijakan lebih awal/lebih akhir dipilih
Tidak ada Tepat tengah malam tidak ada Laporkan bahwa persyaratan tidak dapat dipenuhi dengan masukan tersebut

Program di bawah menerapkan aturan ini dengan mencoba kedua nilai fold, mengonversi setiap kandidat ke UTC, lalu mengonversinya kembali ke zona bernama. Kandidat hanya dipertahankan jika kolom lokal yang dikembalikan sama persis dengan tengah malam yang diminta. Hasil UTC yang duplikat digabungkan menjadi satu kandidat. Urutan validasi ini diturunkan dari perilaku konversi dan fold yang didokumentasikan; ini merupakan logika tambahan pada aplikasi. datetime.astimezone(), PEP 495

Bagaimana menjalankan perhitungan di Terminal Mac?

Buka Spotlight, ketik Terminal, lalu buka aplikasinya. Cara lain, buka /Applications/Utilities di Finder, lalu klik dua kali Terminal. Keduanya adalah cara membuka jendela perintah yang didokumentasikan Apple. Membuka atau menutup Terminal di Mac

Jalankan perintah berikut untuk memeriksa versi Python Anda:

python3 --version

Contoh ini memerlukan Python 3.9 atau yang lebih baru, saat zoneinfo mulai tersedia. Jika Python tidak ada atau versinya lebih lama, ikuti panduan instalasi macOS resmi untuk mendapatkan penginstal Python yang saat ini didukung dari Python.org, lalu ulangi pemeriksaan versi. Alur kerja ini menggunakan modul pustaka standar. zoneinfo — Dukungan zona waktu IANA, Menggunakan Python di macOS

Salin seluruh blok di bawah ini ke Terminal dan tekan Return. Ini adalah perintah lengkap yang berisi program Python. Untuk menghitung stempel waktu publikasi lain, ubah DATE_TEXT dan ZONE_NAME sebelum menempelkan perintah. Biarkan REPEATED sebagai reject kecuali Anda sengaja telah memilih kebijakan untuk tengah malam yang berulang.

python3 - <<'PY'
from datetime import date, datetime, time, timezone
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError

DATE_TEXT = '2025-07-15'
ZONE_NAME = 'America/New_York'
REPEATED = 'reject'  # 'reject', 'earlier', or 'later'


def resolve_midnight(date_text, zone_name, repeated='reject'):
    if repeated not in {'reject', 'earlier', 'later'}:
        raise ValueError('Repeated-time policy must be reject, earlier, or later.')

    day = date.fromisoformat(date_text)
    if day.isoformat() != date_text:
        raise ValueError('Use a date in YYYY-MM-DD format.')

    zone = ZoneInfo(zone_name)
    wall = datetime.combine(day, time.min)
    candidates = set()

    for fold in (0, 1):
        guess = wall.replace(tzinfo=zone, fold=fold)
        instant = guess.astimezone(timezone.utc)
        back = instant.astimezone(zone)
        if back.replace(tzinfo=None) == wall:
            candidates.add(instant)

    ordered = sorted(candidates)
    if not ordered:
        raise ValueError('Exact midnight does not exist on this date in this zone.')

    if len(ordered) == 2 and repeated == 'reject':
        choices = ', '.join(x.isoformat() for x in ordered)
        raise ValueError(
            'Midnight repeats. Choose earlier or later. UTC choices: ' + choices
        )

    chosen = ordered[-1] if repeated == 'later' else ordered[0]
    return chosen.astimezone(zone), chosen


try:
    local, utc = resolve_midnight(DATE_TEXT, ZONE_NAME, REPEATED)
except ZoneInfoNotFoundError:
    raise SystemExit(
        'Zone not found. Check the IANA name and time zone data installation.'
    )
except (ValueError, OverflowError) as exc:
    raise SystemExit(str(exc))

print('Civil date:', DATE_TEXT)
print('Named zone:', ZONE_NAME)
print('Local midnight:', local.isoformat())
print('UTC instant:', utc.isoformat().replace('+00:00', 'Z'))
PY

Untuk contoh yang diberikan, hasilnya adalah:

Civil date: 2025-07-15
Named zone: America/New_York
Local midnight: 2025-07-15T00:00:00-04:00
UTC instant: 2025-07-15T04:00:00Z

Baca kedua baris stempel waktu tersebut secara bersamaan. Baris lokal memastikan bahwa waktu pada jam dinding yang diminta adalah tengah malam. Baris UTC menunjukkan momen yang sama: mengurangi offset lokal sebesar negatif empat jam menghasilkan 04:00:00 UTC. RFC 3339 mendefinisikan stempel waktu menggunakan tanggal, waktu, dan offset numerik atau Z. RFC 3339: Tanggal dan Waktu di Internet: Stempel Waktu

Bagaimana cara memeriksa hasil biasa dan pengecualian?

Masukan berikut adalah contoh publikasi sintetis yang dipilih untuk menguji program. Hasilnya dihitung dengan resolver di atas menggunakan basis data zona waktu yang tersedia; hasil ini bukan catatan publikasi sungguhan. Ubah kedua nilai masukan dan jalankan kembali seluruh perintah untuk setiap kasus.

Tanggal Zona bernama Hasil resolver
2025-01-15 America/New_York Satu waktu: 2025-01-15T05:00:00Z
2025-07-15 America/New_York Satu waktu: 2025-07-15T04:00:00Z
2018-11-04 America/Sao_Paulo Tepat tengah malam tidak ada; ditolak
2020-11-01 America/Havana Tengah malam berulang; secara default ditolak
2011-12-30 Pacific/Apia Tepat tengah malam tidak ada; ditolak

Dua baris pertama menunjukkan mengapa tanggal perlu disertakan dalam perhitungan: zona bernama yang sama menentukan tengah malam pada jam UTC yang berbeda. Untuk contoh Havana yang berulang, menetapkan REPEATED = 'earlier' akan memilih 2020-11-01T04:00:00Z; menetapkannya ke later akan memilih 2020-11-01T05:00:00Z. Nama tersebut merujuk pada urutan kronologis di linimasa UTC.

Hasil tengah malam yang tidak ada memerlukan keputusan tentang persyaratan publikasi. Jika tengah malam tepat sangat penting, pilih tanggal atau zona lain secara eksplisit. Jika yang dimaksud adalah waktu valid pertama pada tanggal tersebut, definisikan dan implementasikan operasi itu secara terpisah, termasuk tindakan saat seluruh tanggal tidak ada. Resolver ini sengaja melaporkan kegagalan alih-alih diam-diam mengganti waktu lokal dengan waktu lain.

Apa yang harus dilakukan jika masukan gagal?

Untuk kesalahan tanggal, masukkan tanggal Gregorian yang valid dalam format YYYY-MM-DD, seperti 2025-07-15. Program memeriksa validitas kalender sekaligus kesesuaian dengan format tersebut. Masukan seperti 2025-02-30 akan gagal, alih-alih dialihkan ke bulan berikutnya.

Untuk Zone not found, periksa pengenal IANA lengkap, termasuk ejaan dan penggunaan huruf besar-kecil. Python mendokumentasikan bahwa pengecualian ini dapat berarti kunci tidak valid atau data zona waktu tidak tersedia. Pencarian standar Python menggunakan data sistem terlebih dahulu dan paket pihak pertama tzdata sebagai cadangan. Jika datanya tidak ada, instal paket tersebut ke lingkungan Python yang Anda gunakan, lalu jalankan kembali resolver. PEP 615 – Dukungan untuk Basis Data Zona Waktu IANA di Pustaka Standar

Simpan tanggal asli, nama zona, pilihan untuk waktu berulang, dan stempel waktu UTC hasil perhitungan bersama dalam catatan kerja Anda. Jika perhitungan berbeda antarkomputer, bandingkan sumber data zona waktunya. Memasang paket cadangan tidak otomatis menggantikan data sistem yang sudah ditemukan Python. Sumber data zoneinfo

Nilai mana yang harus disalin ke alat lain?

Jika tujuan menerima stempel waktu UTC, salin nilai UTC instant, termasuk Z-nya. Pastikan format masukan yang didokumentasikan tujuan sebelum memasukkannya. Kolom tanggal biasa tidak dapat mempertahankan semua informasi yang diwakili stempel waktu hasil perhitungan tersebut; simpan tanggal asli dan zona bernama bersamanya jika Anda perlu mempertahankan maksud penjadwalan.

RFC 9557 mendefinisikan format stempel waktu diperluas yang dapat menyertakan akhiran zona bernama, tetapi format tersebut tetap merepresentasikan waktu yang telah ditentukan. RFC itu juga mengakui bahwa pembaruan data zona dapat menimbulkan inkonsistensi antara offset tersimpan dan informasi zona. Gunakan representasi diperluas hanya jika alat penerima mendokumentasikan dukungannya. RFC 9557, cakupan dan offset yang tidak konsisten

Akhiri dengan memeriksa bahwa keluaran lokal menunjukkan tanggal yang Anda maksud pada 00:00:00, nama zona sesuai dengan masukan, dan pilihan untuk tengah malam berulang memang disengaja. Setelah semua pemeriksaan tersebut lolos, keluaran UTC adalah waktu tengah malam hasil penentuan berdasarkan aturan yang digunakan dalam perhitungan itu.

Sumber