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