Om een publicatiedatum en benoemde tijdzone om te zetten naar een exact moment om middernacht, bepaal je de lokale tijd 00:00:00 met de regels van die zone, controleer je of die tijd bestaat en zet je die vervolgens om naar UTC. Deze Terminal-werkwijze voor Mac detecteert ook herhaalde middernachten.
Stel dat een synthetisch publicatierecord de datum 2025-07-15 en de zone America/New_York bevat. Je taak is de tijdstempel te berekenen die middernacht aan het begin van die datum weergeeft. De onderstaande werkwijze levert een tijdstempel op die je kunt kopiëren naar een tool die UTC accepteert, terwijl de oorspronkelijke datum en zone zichtbaar blijven om ze te controleren.
Welke informatie bepaalt een moment om middernacht?
Houd deze vier waarden gedurende de hele berekening gescheiden:
| Waarde | Synthetisch voorbeeld | Betekenis |
|---|---|---|
| Burgerlijke datum | 2025-07-15 |
Een Gregoriaanse kalenderdatum zonder tijd of zone |
| Lokale datum en tijd | 2025-07-15T00:00:00 |
De gevraagde kloktijd |
| Benoemde tijdzone | America/New_York |
De regels waarmee die lokale tijd wordt geïnterpreteerd |
| Bepaald moment | 2025-07-15T04:00:00Z |
Eén specifiek moment uitgedrukt in UTC |
Python geeft een kalenderdatum weer met date, combineert datum- en tijdvelden met datetime en gebruikt tijdzonegegevens om een tijdzonebewuste datetime te interpreteren. De klasse timezone geeft vaste offsets weer; zoneinfo levert regels voor benoemde tijdzones. Zie de officiële datetime-documentatie en zoneinfo-documentatie.
Een offset zoals -04:00 is het verschil tussen de lokale tijd en UTC voor een bepaalde tijd. Een benoemde zone levert regels die op verschillende datums verschillende offsets kunnen opleveren. RFC 9557 legt uit waarom het vervangen van een benoemde zone door een vaste offset kan leiden tot onjuiste vervolgcalculaties. Behoud de zonenaam in plaats van een offset uit een ander publicatierecord over te nemen. RFC 9557: Datum en tijd op internet: tijdstempels met aanvullende informatie
Voor deze taak betekent ‘middernacht’ precies 00:00:00 aan het begin van de opgegeven datum. Maak deze vereiste expliciet voordat je iets berekent: voor een verzoek om het eerste geldige moment van een kalenderdag is een ander beleid nodig wanneer middernacht ontbreekt.
Waarom moet je middernacht controleren voordat je de tijd omzet?
Lokale klokveranderingen kunnen een gat veroorzaken, waarin een kloktijd niet voorkomt, of een herhaling, waarin een kloktijd twee keer voorkomt. PEP 495 van Python definieert deze gevallen en biedt het attribuut fold om herhaalde tijden te onderscheiden. Ook wordt uitgelegd dat constructors en replace() ontbrekende lokale tijden niet automatisch afwijzen. Een zone koppelen valideert de gevraagde middernacht dus op zichzelf niet. PEP 495 – Onderscheid maken tussen lokale tijden
Gebruik de volgende beslisregel voor een publicatievereiste die exact middernacht voorschrijft:
| Gevonden geldige momenten om middernacht | Interpretatie | Actie |
|---|---|---|
| Eén | Middernacht komt één keer voor | Geef dat moment terug |
| Twee | Middernacht komt twee keer voor | Wijs af totdat een keuze voor eerder/later is gemaakt |
| Geen | Exact middernacht ontbreekt | Meld dat met deze invoer niet aan de vereiste kan worden voldaan |
Het onderstaande programma voert deze regel uit door beide fold-waarden te proberen, elke kandidaat naar UTC om te zetten en die vervolgens terug te zetten naar de benoemde zone. Een kandidaat blijft alleen over als de teruggegeven lokale velden exact overeenkomen met de gevraagde middernacht. Dubbele UTC-resultaten worden samengevoegd tot één kandidaat. Deze validatiestappen zijn afgeleid van het gedocumenteerde gedrag van tijdconversie en folds; het gaat om aanvullende applicatielogica. datetime.astimezone(), PEP 495
Hoe voer je de berekening uit in Terminal op een Mac?
Open Spotlight, typ Terminal en open de app. Je kunt ook /Applications/Utilities openen in Finder en dubbelklikken op Terminal. Dit zijn de door Apple gedocumenteerde manieren om een opdrachtvenster te openen. Terminal openen of afsluiten op de Mac
Voer de volgende opdracht uit om je Python-versie te controleren:
python3 --version
Dit voorbeeld vereist Python 3.9 of hoger, waarin zoneinfo beschikbaar kwam. Als Python ontbreekt of ouder is, volg je de officiële installatiehandleiding voor macOS om een momenteel ondersteund Python-installatieprogramma van Python.org te verkrijgen. Controleer daarna opnieuw de versie. De werkwijze gebruikt modules uit de standaardbibliotheek. zoneinfo — IANA-tijdzoneondersteuning, Python gebruiken op macOS
Kopieer het hele onderstaande blok naar Terminal en druk op Return. Het is een volledige opdracht met het Python-programma. Als je een andere publicatietijdstempel wilt berekenen, pas je DATE_TEXT en ZONE_NAME aan voordat je het blok plakt. Laat REPEATED op reject staan, tenzij je bewust een beleid voor herhaalde middernacht hebt gekozen.
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
Voor het opgegeven voorbeeld is de uitvoer:
Burgerlijke datum: 2025-07-15
Benoemde zone: America/New_York
Lokale middernacht: 2025-07-15T00:00:00-04:00
UTC-moment: 2025-07-15T04:00:00Z
Lees de twee tijdstempelregels samen. De lokale regel bevestigt dat de gevraagde kloktijd middernacht is. De UTC-regel geeft hetzelfde moment aan: als je de lokale offset van min vier uur aftrekt, krijg je 04:00:00 UTC. RFC 3339 definieert een tijdstempel met een datum, tijd en een numerieke offset of Z. RFC 3339: Datum en tijd op internet: tijdstempels
Hoe controleer je gewone en uitzonderlijke resultaten?
De volgende invoerwaarden zijn synthetische publicatievoorbeelden die zijn geselecteerd om het programma te testen. De resultaten zijn berekend met de bovenstaande resolver en de beschikbare tijdzonedatabase; het zijn geen gegevens van echte publicaties. Wijzig de twee invoerwaarden en voer de volledige opdracht voor elk geval opnieuw uit.
| Datum | Benoemde zone | Resultaat van de resolver |
|---|---|---|
2025-01-15 |
America/New_York |
Eén moment: 2025-01-15T05:00:00Z |
2025-07-15 |
America/New_York |
Eén moment: 2025-07-15T04:00:00Z |
2018-11-04 |
America/Sao_Paulo |
Exacte middernacht ontbreekt; wordt afgewezen |
2020-11-01 |
America/Havana |
Middernacht komt twee keer voor; standaard afgewezen |
2011-12-30 |
Pacific/Apia |
Exacte middernacht ontbreekt; wordt afgewezen |
De eerste twee rijen laten zien waarom de datum onderdeel is van de berekening: in dezelfde benoemde zone wordt middernacht omgezet naar verschillende UTC-uren. Voor het voorbeeld met de herhaalde middernacht in Havana selecteert REPEATED = 'earlier' 2020-11-01T04:00:00Z; als je dit instelt op later, wordt 2020-11-01T05:00:00Z geselecteerd. De namen verwijzen naar de chronologische volgorde op de UTC-tijdlijn.
Bij een ontbrekende middernacht moet je een beslissing nemen over de publicatievereiste. Als exact middernacht essentieel is, kies dan expliciet een andere datum of zone. Als je eigenlijk de eerste geldige tijd op die datum bedoelt, definieer en implementeer die bewerking afzonderlijk, inclusief wat er moet gebeuren als de hele datum ontbreekt. Deze resolver meldt bewust een fout in plaats van ongemerkt een andere lokale tijd te gebruiken.
Wat moet je doen als een invoerwaarde een fout oplevert?
Bij een datumfout geef je een echte Gregoriaanse datum op in de vorm YYYY-MM-DD, zoals 2025-07-15. Het programma controleert zowel of de datum op de kalender bestaat als of de opmaak exact klopt. Een invoer zoals 2025-02-30 levert een fout op in plaats van naar een andere maand te worden doorgeschoven.
Controleer bij Zone not found de volledige IANA-aanduiding, inclusief spelling en hoofdletters. Python documenteert dat deze uitzondering zowel een ongeldige sleutel als ontbrekende tijdzonegegevens kan betekenen. Python zoekt standaard eerst in systeemgegevens en gebruikt daarna het door de eerste partij onderhouden pakket tzdata als terugvaloptie. Als de gegevens ontbreken, installeer je dat pakket in de Python-omgeving die je gebruikt en voer je de resolver opnieuw uit. PEP 615 – Ondersteuning voor de IANA-tijdzonedatabase in de standaardbibliotheek
Bewaar de oorspronkelijke datum, zonenaam, keuze bij een herhaalde tijd en de bepaalde UTC-tijdstempel samen in je aantekeningen. Als berekeningen op verschillende computers uiteenlopen, vergelijk dan hun bronnen voor tijdzonegegevens. Het installeren van een terugvalpakket vervangt niet automatisch de systeemgegevens die Python al vindt. zoneinfo-gegevensbronnen
Welke waarde moet je naar een andere tool kopiëren?
Als de bestemming een UTC-tijdstempel accepteert, kopieer je de waarde UTC-moment, inclusief Z. Controleer de gedocumenteerde invoerindeling van de bestemming voordat je de waarde invoert. Een gewoon datumveld kan niet alle informatie behouden die in die bepaalde tijdstempel is vastgelegd; bewaar de oorspronkelijke datum en benoemde zone erbij als je de geplande bedoeling wilt behouden.
RFC 9557 definieert een uitgebreide tijdstempelindeling die een achtervoegsel met een benoemde zone kan bevatten, maar ook die indeling geeft een bepaald moment weer. De standaard erkent ook dat updates van zonegegevens inconsistenties kunnen veroorzaken tussen opgeslagen offsets en zonegegevens. Gebruik een uitgebreide weergave alleen als de ontvangende tool ondersteuning daarvoor documenteert. RFC 9557, reikwijdte en inconsistente offsets
Controleer tot slot of de lokale uitvoer de bedoelde datum op 00:00:00 toont, of de benoemde zone overeenkomt met je invoer en of je een eventuele keuze bij herhaalde middernacht bewust hebt gemaakt. Zodra deze controles zijn geslaagd, is de UTC-uitvoer het bepaalde moment van middernacht volgens de regels die bij die berekening zijn gebruikt.
Bronnen
- Terminal openen of afsluiten op de Mac — Apple
- Python gebruiken op macOS — Python Software Foundation
- datetime — Basissoorten voor datum en tijd — Python Software Foundation
- zoneinfo — IANA-tijdzoneondersteuning — Python Software Foundation
- PEP 495 – Onderscheid maken tussen lokale tijden — Python Software Foundation
- PEP 615 – Ondersteuning voor de IANA-tijdzonedatabase in de standaardbibliotheek — Python Software Foundation
- RFC 3339: Datum en tijd op internet: tijdstempels — RFC Editor
- RFC 9557: Datum en tijd op internet: tijdstempels met aanvullende informatie — RFC Editor