Aby odjąć dokładną liczbę godzin od znacznika czasu UTC na Macu, sparsuj go z jego przesunięciem UTC, odejmij czas trwania i jawnie podaj wynik w UTC. Ten proces w Terminalu wykorzystuje Pythona i syntetyczną datę publikacji.
Zadanie jest konkretne: cofnąć znacznik czasu publikacji o nieujemną całkowitą liczbę godzin, zachowując UTC zarówno na wejściu, jak i na wyjściu. Na przykład odjęcie siedmiu godzin od 2026-05-12T02:30:00Z daje 2026-05-11T19:30:00Z.
„Dokładność” wynika z udokumentowanego modelu daty i czasu w Pythonie: jedna godzina to 3600 sekund, a sekundy przestępne nie są reprezentowane. Ten proces nadaje się więc do typowych znaczników czasu publikacji; obliczenia, które muszą uwzględniać sekundy przestępne, wymagają innego modelu czasu. Dokumentacja datetime w Pythonie
Od jakiego rodzaju daty zaczynasz?
Przed obliczeniami rozróżnij datę kalendarzową od znacznika czasu. Data taka jak 2026-05-12 nie określa, kiedy następuje publikacja. Dodanie północy albo założenie lokalnej strefy czasowej Maca wprowadziłoby informacje, których nie podano.
| Pojęcie | Syntetyczny przykład | Co określa |
|---|---|---|
| Data cywilna | 2026-05-12 |
Dzień kalendarzowy bez godziny i przesunięcia |
| Lokalna data i godzina | 2026-05-12T02:30:00 |
Pola zegara bez wystarczającego kontekstu, by wskazać konkretną chwilę |
| Chwila wyrażona w UTC | 2026-05-12T02:30:00Z |
Konkretny punkt w czasie |
| Przesunięcie liczbowe | +00:00 |
Podana różnica względem UTC |
| Nazwana strefa czasowa | Europe/Paris |
Reguły wiążące lokalne odczyty zegara z UTC |
Przesunięcie i nazwana strefa mają różne zastosowania. Przesunięcie liczbowe określa relację znacznika czasu do UTC; nazwana strefa podaje reguły, które mogą zależeć od daty. RFC 9557 definiuje te rozróżnienia i wyjaśnia, dlaczego niektóre lokalne wskazania zegara mogą odpowiadać zeru lub wielu chwilom. RFC 9557, definicje
Do tego zadania użyj pełnego znacznika czasu. Poniższy program akceptuje wielką literę T, sekundy, opcjonalny ułamek sekundy o długości od jednej do sześciu cyfr oraz Z lub +00:00. To celowo ograniczony podzbiór RFC 3339, którego gramatyka znaczników czasu dopuszcza również inne przesunięcia i więcej cyfr ułamka. RFC 3339, format daty i czasu
Jak odjąć godziny w Terminalu?
Przygotuj Pythona na Macu
Otwórz Findera, przejdź do /Applications/Utilities i kliknij dwukrotnie Terminal. Apple opisuje to jako jeden ze sposobów otwierania aplikacji wiersza poleceń. Otwieranie i zamykanie Terminala na Macu
Wpisz to polecenie i naciśnij Return:
python3 --version
W tym przewodniku użyj Pythona 3.11 lub nowszego. Jeśli nie masz odpowiedniego interpretera, postępuj zgodnie z oficjalnymi instrukcjami instalacji w systemie macOS: pobierz obsługiwany instalator Pythona ze wskazanej strony pobierania dla macOS, otwórz jego plik .pkg i wykonaj opisane kroki instalacji. Następnie otwórz nowe okno Terminala i ponownie sprawdź wersję. Dokumentacja Pythona opisuje zarówno instalację, jak i uruchamianie Pythona z powłoki. Korzystanie z Pythona w systemie macOS
Wykonaj całe obliczenie
Skopiuj cały poniższy blok do Terminala, łącznie z pierwszym i ostatnim wierszem, a następnie naciśnij Return. Aby wykonać kolejne obliczenie, przed wklejeniem zmień tylko source_timestamp i hours_to_subtract. Pozostaw znacznik czasu w cudzysłowie i wpisz liczbę godzin jako liczbę całkowitą.
python3 - <<'PY'
import re
from datetime import datetime, timedelta, timezone
source_timestamp = "2026-05-12T02:30:00Z"
hours_to_subtract = 7
def subtract_utc_hours(text, hours):
if type(hours) is not int or hours < 0:
raise ValueError("Hours must be a non-negative whole number.")
match = re.fullmatch(
r"[0-9]{4}-[0-9]{2}-[0-9]{2}T"
r"[0-9]{2}:[0-9]{2}:[0-9]{2}"
r"(?P<fraction>\.[0-9]{1,6})?(?:Z|\+00:00)",
text,
)
if match is None:
raise ValueError(
"Use YYYY-MM-DDTHH:MM:SS, optionally .ffffff, "
"ending in Z or +00:00."
)
normalized = text[:-1] + "+00:00" if text.endswith("Z") else text
start = datetime.fromisoformat(normalized).astimezone(timezone.utc)
try:
result = start - timedelta(hours=hours)
except OverflowError as exc:
raise ValueError(
"The duration or result is outside the supported range."
) from exc
# Whole-hour subtraction leaves the fractional second unchanged.
seconds_text = result.isoformat(timespec="seconds")
return seconds_text[:-6] + (match.group("fraction") or "") + "Z"
try:
print(subtract_utc_hours(source_timestamp, hours_to_subtract))
except ValueError as exc:
raise SystemExit(f"Cannot subtract: {exc}")
PY
Wynik dla podanego syntetycznego znacznika czasu publikacji:
2026-05-11T19:30:00Z
To kompletny program korzystający ze standardowej biblioteki Pythona. Wyświetla obliczony znacznik czasu, nie tworząc pliku. Skopiuj wynik do pola daty publikacji lub dokumentu, który przygotowujesz.
Kolejność operacji API to datetime.fromisoformat(), konwersja do timezone.utc, odjęcie timedelta(hours=hours) i wyświetlenie wyniku za pomocą isoformat(). Python dokumentuje te operacje parsowania, obsługi stref czasowych, czasu trwania i formatowania. Interfejsy API datetime w Pythonie
Jak program zachowuje UTC i ułamki sekund?
Sprawdzenie danych wejściowych wymaga jawnego zapisu UTC. Znacznik czasu bez przesunięcia jest od razu odrzucany, więc program nie musi ustalać strefy na podstawie ustawień Maca. Oba akceptowane sufiksy są parsowane jako znaczniki czasu z przesunięciem zerowym, a wynik jest zawsze zapisywany z użyciem Z.
Zachowanie UTC nie oznacza zachowania każdego znaku z pierwotnego ciągu. Dane wejściowe kończące się na +00:00 wracają z końcówką Z. Wynik zachowuje zapis UTC, a data i godzina cofają się o żądany czas trwania.
Program zachowuje również podany zapis ułamka sekundy. Odjęcie całych godzin pozostawia ten ułamek bez zmian, więc .120 pozostaje .120, zamiast zmienić się w .12 lub zniknąć. Dane z więcej niż sześcioma cyframi po przecinku są odrzucane, a nie skracane.
Warto znać niuans związany ze standardami: Z oznacza zerowe przesunięcie UTC, ale nie określa strefy czasowej miejsca, z którego pochodzi znacznik czasu. RFC 9557 aktualizuje interpretację Z w RFC 3339, dopuszczając nieznane lokalne przesunięcie. Ten program celowo akceptuje Z i +00:00; odrzuca zaś -00:00 zgodnie z przyjętą polityką danych wejściowych. RFC 9557, aktualizacja RFC 3339
Jak sprawdzić wynik przed użyciem?
Zacznij od obliczenia przechodzącego przez północ. W głównym przykładzie cofnięcie o dwie godziny daje 00:30:00 12 maja; cofnięcie o kolejne pięć godzin daje 19:30:00 11 maja. Wynik pozostający 12 maja byłby nieprawidłowy.
Te syntetyczne przykłady pozwalają przeprowadzić dodatkowe kontrole. Zmień dwie wartości wejściowe w kompletnym programie, aby uzyskać wyniki z poszczególnych wierszy.
| Wejściowy czas UTC | Odjęte godziny | Oczekiwany wynik UTC |
|---|---|---|
2026-05-12T02:30:00Z |
7 | 2026-05-11T19:30:00Z |
2026-01-01T00:15:00+00:00 |
1 | 2025-12-31T23:15:00Z |
2028-03-01T00:30:00Z |
1 | 2028-02-29T23:30:00Z |
2026-05-12T02:30:00.120Z |
7 | 2026-05-11T19:30:00.120Z |
2026-05-12T02:30:00Z |
0 | 2026-05-12T02:30:00Z |
W głównym przykładzie przedział wynosi siedem razy 3600, czyli 25 200 sekund. Minuty i sekundy pozostają bez zmian, ponieważ żądany czas trwania obejmuje tylko całe godziny. Data może zmienić się po przekroczeniu północy, końca miesiąca lub końca roku.
Co zrobić, gdy dane wejściowe zostaną odrzucone?
Potraktuj odrzucenie jako wskazówkę diagnostyczną. Przed ponowną próbą uzupełnij brakujące informacje lub dostosuj nieobsługiwaną precyzję.
- Dostępna jest tylko data: Ustal zamierzoną godzinę publikacji i jej przesunięcie. Sama data cywilna nie wskazuje początkowej chwili.
- Znacznik czasu nie ma przesunięcia: Zanim dodasz sufiks, potwierdź, czy oznacza UTC, czy czas lokalny.
- Znacznik czasu ma niezerowe przesunięcie: Najpierw przelicz wskazaną chwilę na UTC. Sama zmiana sufiksu zmieniłaby znaczenie.
- Ułamek sekundy ma więcej niż sześć cyfr: Użyj narzędzia zachowującego tę precyzję albo przed użyciem tego procesu przyjmij jawną regułę zaokrąglania.
- Liczba godzin jest ujemna lub ułamkowa: Podaj nieujemną liczbę całkowitą. Program celowo obsługuje odejmowanie całych godzin.
- Pola kalendarzowe są nieprawidłowe: Popraw wartość źródłową. Niemożliwa data, na przykład 30 lutego, zostanie odrzucona.
Python obsługuje lata datetime od 1 do 9999; odejmowanie wykraczające poza ten zakres kończy się błędem. Model datetime w Pythonie odrzuca również wartość sekund 60, mimo że RFC 3339 dopuszcza ją w określonych warunkach jako sekundę przestępną. Ograniczenia datetime w Pythonie, RFC 3339, ograniczenia
Jeśli w rzeczywistości potrzebujesz „tej samej lokalnej godziny zegarowej poprzedniego dnia”, użyj kalendarzowego procesu uwzględniającego nazwaną strefę. Przesunięcie w nazwanej strefie może zmieniać się przy przejściu na czas letni, więc takie zadanie może dać inny wynik niż odjęcie 24 godzin czasu, które upłynęły. Dokumentacja zoneinfo w Pythonie pokazuje obliczenia obejmujące takie zmiany. Obsługa stref czasowych IANA w Pythonie
W przypadku znacznika czasu publikacji wyrażonego już w UTC skup się na właściwych operacjach: sprawdź dane wejściowe, odejmij czas trwania będący całkowitą liczbą godzin i zachowaj jawny sufiks UTC w kopiowanej wartości. Przed użyciem wyniku sprawdź granicę daty i precyzję ułamka sekundy.
Źródła
- datetime — podstawowe typy daty i czasu — Python Software Foundation.
- Korzystanie z Pythona w systemie macOS — Python Software Foundation.
- Otwieranie i zamykanie Terminala na Macu — Apple.
- RFC 3339: data i czas w Internecie: znaczniki czasu — RFC Editor.
- RFC 9557: data i czas w Internecie: znaczniki czasu z dodatkowymi informacjami — RFC Editor.
- zoneinfo — obsługa stref czasowych IANA — Python Software Foundation.