Om du vill omvandla ett publiceringsdatum och en namngiven tidszon till ett exakt midnattsögonblick löser du lokal 00:00:00 enligt tidszonens regler, kontrollerar att den finns och omvandlar den sedan till UTC. Det här arbetsflödet i Mac Terminal upptäcker även upprepade midnätter.
Anta att en syntetisk publiceringspost innehåller datumet 2025-07-15 och tidszonen America/New_York. Din uppgift är att beräkna tidsstämpeln som motsvarar midnatt i början av det datumet. Arbetsflödet nedan ger en tidsstämpel som du kan kopiera till ett verktyg som tar emot UTC, samtidigt som det ursprungliga datumet och tidszonen visas så att du kan kontrollera dem.
Vilken information definierar ett midnattsögonblick?
Håll dessa fyra värden åtskilda under hela beräkningen:
| Värde | Syntetiskt exempel | Betydelse |
|---|---|---|
| Kalenderdatum | 2025-07-15 |
Ett gregorianskt kalenderdatum utan klockslag eller tidszon |
| Lokalt datum och klockslag | 2025-07-15T00:00:00 |
Den efterfrågade lokala klocktiden |
| Namngiven tidszon | America/New_York |
Reglerna som används för att tolka den lokala tiden |
| Löst ögonblick | 2025-07-15T04:00:00Z |
Ett specifikt ögonblick uttryckt i UTC |
Python representerar ett kalenderdatum med date, kombinerar datum- och tidsfält med datetime och använder tidszoninformation för att tolka en tidszonsmedveten datetime. Klassen timezone representerar fasta förskjutningar; zoneinfo tillhandahåller regler för namngivna tidszoner. Se den officiella datetime-dokumentationen och zoneinfo-dokumentationen.
En förskjutning som -04:00 är skillnaden mellan lokal tid och UTC för en viss avläsning. En namngiven tidszon tillhandahåller regler som kan ge olika förskjutningar på olika datum. RFC 9557 förklarar varför det kan leda till felaktiga efterföljande beräkningar att ersätta en namngiven tidszon med en fast förskjutning. Behåll tidszonens namn i stället för att kopiera en förskjutning från en annan publiceringspost. RFC 9557: Datum och tid på internet: tidsstämplar med ytterligare information
I den här uppgiften betyder ”midnatt” exakt 00:00:00 i början av det angivna datumet. Gör det kravet tydligt innan du börjar räkna: en begäran om dagens första giltiga ögonblick kräver en annan hantering när midnatt saknas.
Varför måste midnatt kontrolleras före konverteringen?
Lokala klockändringar kan skapa ett glapp, då en viss klocktid inte inträffar, eller en upprepning, då den inträffar två gånger. PEP 495 i Python definierar dessa fall och tillhandahåller attributet fold för att skilja upprepade tider åt. Dokumentet beskriver också att konstruktorer och replace() inte automatiskt avvisar lokala tider som saknas. Att koppla på en tidszon validerar alltså inte i sig den begärda midnatten. PEP 495 – Tvetydiga lokala tider
Använd följande beslutsregel för ett krav på exakt midnatt vid publicering:
| Antal giltiga midnattsögonblick | Tolkning | Åtgärd |
|---|---|---|
| Ett | Midnatt är entydig | Returnera det ögonblicket |
| Två | Midnatt upprepas | Avvisa tills en policy för tidigare/senare tid har valts |
| Inget | Exakt midnatt saknas | Rapportera att kravet inte kan uppfyllas med dessa indata |
Programmet nedan tillämpar regeln genom att prova båda fold-värdena, konvertera varje kandidat till UTC och sedan konvertera tillbaka till den namngivna tidszonen. En kandidat godkänns bara om de lokala fälten efter konverteringen exakt motsvarar den begärda midnatten. Dubbletter av UTC-resultat slås ihop till en kandidat. Den här valideringssekvensen bygger på det dokumenterade konverterings- och fold-beteendet; den är ytterligare programlogik. datetime.astimezone(), PEP 495
Hur kör du beräkningen i Mac Terminal?
Öppna Spotlight, skriv Terminal och öppna appen. Alternativt kan du öppna /Applications/Utilities i Finder och dubbelklicka på Terminal. Det här är Apples dokumenterade sätt att öppna ett kommandofönster. Öppna eller avsluta Terminal på Mac
Kör följande kommando för att kontrollera din Python-version:
python3 --version
Det här exemplet kräver Python 3.9 eller senare, där zoneinfo blev tillgängligt. Om Python saknas eller är äldre följer du den officiella installationsguiden för macOS för att hämta ett aktuellt Python-installationsprogram från Python.org och upprepar sedan versionskontrollen. Arbetsflödet använder moduler i standardbiblioteket. zoneinfo — stöd för IANA-tidszoner, Använda Python på macOS
Kopiera hela blocket nedan till Terminal och tryck på Return. Det är ett komplett kommando som innehåller Python-programmet. Om du vill beräkna en annan publiceringstidsstämpel redigerar du DATE_TEXT och ZONE_NAME innan du klistrar in blocket. Låt REPEATED vara reject om du inte medvetet har valt en policy för upprepad midnatt.
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
För det angivna exemplet blir resultatet:
Kalenderdatum: 2025-07-15
Namngiven tidszon: America/New_York
Lokal midnatt: 2025-07-15T00:00:00-04:00
UTC-ögonblick: 2025-07-15T04:00:00Z
Läs de två tidsstämpelraderna tillsammans. Den lokala raden bekräftar att den begärda lokala tiden är midnatt. UTC-raden anger samma ögonblick: om du drar bort den lokala förskjutningen på minus fyra timmar får du 04:00:00 UTC. RFC 3339 definierar en tidsstämpel med ett datum, ett klockslag och antingen en numerisk förskjutning eller Z. RFC 3339: Datum och tid på internet: tidsstämplar
Hur kontrollerar du vanliga och exceptionella resultat?
Indata nedan är syntetiska publiceringsexempel som valts för att testa programmet. Resultaten beräknades med ovanstående lösare och den tillgängliga tidszonsdatabasen; de motsvarar inte faktiska publiceringar. Ändra de två indatavärdena och kör hela kommandot igen för varje fall.
| Datum | Namngiven tidszon | Resultat från lösaren |
|---|---|---|
2025-01-15 |
America/New_York |
Ett ögonblick: 2025-01-15T05:00:00Z |
2025-07-15 |
America/New_York |
Ett ögonblick: 2025-07-15T04:00:00Z |
2018-11-04 |
America/Sao_Paulo |
Exakt midnatt saknas; avvisas |
2020-11-01 |
America/Havana |
Midnatt upprepas; avvisas som standard |
2011-12-30 |
Pacific/Apia |
Exakt midnatt saknas; avvisas |
De två första raderna visar varför datumet ingår i beräkningen: midnatt i samma namngivna tidszon motsvarar olika UTC-timmar. För exemplet med upprepad midnatt i Havanna väljer REPEATED = 'earlier' 2020-11-01T04:00:00Z; om du anger later väljs 2020-11-01T05:00:00Z. Namnen syftar på kronologisk ordning på UTC-tidslinjen.
Ett resultat som anger att midnatt saknas kräver ett beslut om publiceringskravet. Om exakt midnatt är nödvändig väljer du uttryckligen ett annat datum eller en annan tidszon. Om kravet i stället är dagens första giltiga tid definierar och implementerar du den åtgärden separat, inklusive hur du ska hantera ett datum som inte finns alls. Den här lösaren rapporterar medvetet ett misslyckande i stället för att i tysthet ersätta tiden med en annan lokal tid.
Vad gör du när en indata inte fungerar?
Om datumet är fel anger du ett giltigt gregorianskt datum i formatet YYYY-MM-DD, till exempel 2025-07-15. Programmet kontrollerar både kalenderns giltighet och att formatet är exakt. En indata som 2025-02-30 avvisas i stället för att flyttas över till en annan månad.
Om felet är Zone not found kontrollerar du hela IANA-identifieraren, inklusive stavning och versaler. Python-dokumentationen anger att undantaget kan betyda antingen att nyckeln är ogiltig eller att tidszonsdata saknas. Standardsökningen använder först systemdata och därefter förstapartspaketet tzdata som reserv. Om data saknas installerar du paketet i Python-miljön du använder och kör sedan lösaren igen. PEP 615 – Stöd för IANA:s tidszonsdatabas i standardbiblioteket
Spara originaldatumet, tidszonens namn, valet för upprepad tid och den lösta UTC-tidsstämpeln tillsammans i dina arbetsanteckningar. Om beräkningar skiljer sig åt mellan datorer jämför du deras tidszonsdatakällor. Installation av ett reservpaket ersätter inte automatiskt systemdata som Python redan hittar. zoneinfo-datakällor
Vilket värde ska du kopiera till ett annat verktyg?
När målet godtar en UTC-tidsstämpel kopierar du värdet UTC-ögonblick, inklusive dess Z. Kontrollera målets dokumenterade indataformat innan du anger värdet. Ett vanligt datumfält kan inte bevara all information som den lösta tidsstämpeln innehåller; behåll originaldatumet och den namngivna tidszonen tillsammans med den när du behöver spara schemaläggningens avsikt.
RFC 9557 definierar ett utökat tidsstämpelformat som kan innehålla ett suffix med en namngiven tidszon, men formatet representerar fortfarande ett löst ögonblick. Standarden tar också upp att uppdateringar av tidszonsdata kan skapa inkonsekvenser mellan lagrade förskjutningar och tidszoninformation. Använd ett utökat format endast där det mottagande verktyget dokumenterar stöd för det. RFC 9557, omfattning och inkonsekventa förskjutningar
Avsluta med att kontrollera att den lokala utdata visar det avsedda datumet vid 00:00:00, att den namngivna tidszonen stämmer med indata och att eventuella val om upprepad midnatt var avsiktliga. När kontrollerna är klara är UTC-utdata det lösta midnattsögonblicket enligt reglerna som användes i beräkningen.
Källor
- Öppna eller avsluta Terminal på Mac — Apple
- Använda Python på macOS — Python Software Foundation
- datetime — grundläggande datum- och tidstyper — Python Software Foundation
- zoneinfo — stöd för IANA-tidszoner — Python Software Foundation
- PEP 495 – Tvetydiga lokala tider — Python Software Foundation
- PEP 615 – Stöd för IANA:s tidszonsdatabas i standardbiblioteket — Python Software Foundation
- RFC 3339: Datum och tid på internet: tidsstämplar — RFC Editor
- RFC 9557: Datum och tid på internet: tidsstämplar med ytterligare information — RFC Editor