Aby policzyć dni kalendarzowe między datami publikacji, porównaj ich daty, zamiast dzielić liczbę upływających godzin przez 24. Na Macu Numbers obsługuje same daty; znaczniki czasu trzeba najpierw zinterpretować w wybranej strefie czasowej.

W tym przewodniku użyto syntetycznych dat publikacji i kalendarza gregoriańskiego. Zadanie polega na odpowiedzi na pytanie: „Ile dni kalendarzowych dzieli te dwie publikacje?”. Domyślnie obliczana jest różnica ze znakiem: ta sama data daje zero, a następna data — jeden.

Jakiego rodzaju informacje o dacie masz?

Przed obliczeniami wybierz typ danych wejściowych. Data podana w publikacji i znacznik czasu rejestrujący moment jej wydania wymagają innego przygotowania.

Dane wejściowe Znaczenie Przygotowanie
2025-03-09 Data kalendarzowa: rok, miesiąc i dzień Porównaj bezpośrednio z inną datą kalendarza gregoriańskiego
2025-03-09T05:00:00Z Znacznik czasu wskazujący konkretny moment Przelicz na datę w wybranej strefie raportowania
-05:00 Przesunięcie względem UTC Określa różnicę czasu lokalnego względem UTC w danym momencie
America/New_York Nazwana strefa czasowa Zawiera reguły potrzebne do interpretacji dat lokalnych i zmian przesunięcia

Przesunięcie i nazwana strefa zawierają różne informacje. Przesunięcie przypisane do jednego znacznika czasu nie określa przesunięcia w innym dniu. Nazwana strefa zawiera reguły opisujące tę zależność, w tym zmiany czasu. Rozróżnienie to jasno opisano w dokumencie RFC 9557 „Data i czas w Internecie: znaczniki czasu z dodatkowymi informacjami”.

W arkuszu z datami publikacji przyjmij następującą zasadę: zachowuj daty podane jako daty kalendarzowe, a daty ze znaczników czasu wyznaczaj w jednej, jawnie określonej strefie raportowania. Nie przypisuj arbitralnie samej dacie północy i przesunięcia tylko po to, by wykonać odejmowanie.

Standardy kalendarzowe również odróżniają daty od dat i godzin. Standard iCalendar definiuje osobną wartość DATE, która zawiera składowe daty kalendarzowej. W jej postaci serializowanej używa się cyfr bez separatorów; daty z łącznikami w tym przewodniku zastosowano dla czytelności. Zob. RFC 5545, sekcja 3.3.4.

Dlaczego dzielenie liczby upływających sekund przez 86 400 nie działa?

Różnica między datami kalendarzowymi mierzy postęp w kalendarzu. Różnica czasu upływającego mierzy odstęp między dwoma momentami. Podczas zmiany czasu te wielkości nie muszą odpowiadać 24 godzinom na każdy kolejny dzień kalendarzowy. RFC 5545 wyraźnie zaznacza, że nominalny jednodniowy interwał cykliczny może trwać krócej lub dłużej niż 24 godziny, gdy następuje zmiana strefy. Zob. omówienie powtarzania.

Rozważmy dwie syntetyczne pary dat publikacji w strefie America/New_York. Poniższe obliczenia zakładają północ czasu lokalnego w obu punktach końcowych. Przesunięcia wynikają z reguł strefy i zmian czasu obowiązujących w Nowym Jorku, opisanych w bazie stref czasowych IANA.

Syntetyczny przedział publikacji Przesunięcie na początku Przesunięcie na końcu Liczba upływających godzin Różnica dat kalendarzowych
9–10 marca 2025 r. -05:00 -04:00 23 1
2–3 listopada 2025 r. -04:00 -05:00 25 1

Dla marcowej pary odpowiadające chwile w UTC to 2025-03-09T05:00:00Z i 2025-03-10T04:00:00Z: dzieli je 23 godziny. Podzielenie tego przedziału przez 24 daje w przybliżeniu 0.9583. W przypadku listopadowej pary analogiczne obliczenie daje w przybliżeniu 1.0417. Żadna z tych liczb dziesiętnych nie odpowiada na pytanie o dni kalendarzowe.

W tych przykładach zaokrąglenie może ukryć błąd, ale nie stanowi wiarygodnej zasady liczenia. Dwie publikacje opublikowane o 23:55 i 00:05 w kolejne dni dzieli zaledwie dziesięć minut, a różnica ich dat kalendarzowych nadal wynosi jeden. Najpierw wyodrębnij daty, a potem oblicz ich różnicę.

Jak liczyć daty publikacji w Numbers?

Zastosuj tę metodę, jeśli masz już właściwe daty publikacji. Apple dokumentuje, że funkcja DAYS(end-date, start-date) zwraca liczbę dni między argumentami, w tym wartość ujemną, gdy data końcowa poprzedza początkową. Zob. dokumentacja funkcji DAYS w Numbers.

Otwórz arkusz Numbers z pustą tabelą. W wierszu 1 umieść opisowe etykiety, a następnie wprowadź poniższe formuły osobno w wierszu 2. Aby wprowadzić formułę, zaznacz jej komórkę, wpisz początkowy znak =, uzupełnij wyrażenie i naciśnij Return. Są to opisane przez Apple kroki wprowadzania formuł w Numbers na Macu.

Komórka Proponowana etykieta kolumny Formuła do wprowadzenia Oczekiwana wartość
A2 Wcześniejsza data publikacji =DATE(2025,3,9) 9 marca 2025 r.
B2 Późniejsza data publikacji =DATE(2025,3,10) 10 marca 2025 r.
C2 Różnica w dniach kalendarzowych =DAYS(B2,A2) 1

Użycie DATE tworzy wartości wejściowe z roku, miesiąca i dnia, zamiast polegać na sposobie interpretowania niejednoznacznego ciągu tekstowego. Apple zaleca tę funkcję, aby zapewnić spójną interpretację dat przy różnych ustawieniach ich formatu; znajdziesz ją na liście funkcji daty i czasu.

Powtórz sprawdzenie w wierszu 3, używając =DATE(2025,11,2) w komórce A3, =DATE(2025,11,3) w B3 i =DAYS(B3,A3) w C3. Wynik ponownie wynosi 1. Porównujesz podane daty kalendarzowe, więc nie trzeba korygować wyniku o upływające godziny.

Aby szybko obliczyć wynik bez komórek pomocniczych, wpisz =DAYS(DATE(2025,3,10),DATE(2025,3,9)) w dowolnej pustej komórce. Wersja z osobnymi kolumnami jest łatwiejsza do sprawdzenia i ponownego wykorzystania dla wielu par dat publikacji.

Czy potrzebujesz odstępu czy liczby dni z wliczonymi datami krańcowymi?

Standardowa różnica nie wlicza daty początkowej jako liczonej jednostki. Między 9 a 10 marca upływa jeden dzień. Jeśli zadanie pyta, ile dat obejmuje zakres od 9 do 10 marca włącznie, odpowiedź wynosi dwa.

Dla zakresu włącznie, którego data końcowa przypada w dniu początkowym lub później, użyj =DAYS(B2,A2)+1. Przed zastosowaniem tej formuły sprawdź kolejność dat. Ujemna różnica jest przydatną wskazówką, że wpisy mogą być odwrócone; automatyczne użycie wartości bezwzględnej usunęłoby tę informację.

To samo rozróżnienie dotyczy zakresu obejmującego jedną datę. Różnica dat wynosi zero, a liczba dat z wliczonymi krańcami — jeden. Zdecyduj, którego wyniku potrzebuje arkusz, i odpowiednio nazwij kolumnę.

Co zrobić, jeśli dane wejściowe to znaczniki czasu?

Zanim usuniesz informację o godzinie, przelicz znacznik czasu na strefę raportowania. Na przykład 2025-03-10T00:30:00Z odpowiada godzinie 20:30 dnia 9 marca w strefie America/New_York, przy zastosowaniu przesunięcia -04:00 obowiązującego tego dnia. Skopiowanie pierwszych dziesięciu znaków znacznika czasu wybrałoby datę UTC zamiast daty publikacji w Nowym Jorku.

Udokumentowana sygnatura funkcji DAYS w Numbers przyjmuje dwa argumenty będące datami; nie ma argumentu określającego nazwaną strefę. Użyj jej po ustaleniu właściwych dat. Do powtarzalnych obliczeń na znacznikach czasu na Macu niezbędne interfejsy kalendarza udostępnia Foundation.

Mimo swojej nazwy typ Date we Foundation reprezentuje moment niezależnie od kalendarza i strefy czasowej. Apple kieruje obliczenia kalendarzowe do typu Calendar. Zob. oficjalną dokumentację Date.

W przypadku zwykłych zmian czasu sekwencja operacji we Foundation jest następująca: wybierz kalendarz gregoriański i strefę raportowania, znajdź początek lokalnego dnia dla każdego punktu końcowego, a następnie oblicz różnicę, uwzględniając wyłącznie składnik dnia. Apple dokumentuje zarówno startOfDay(for:), jak i dateComponents(_:from:to:).

Uruchom kompletny przykład Foundation w Terminalu

Ta opcjonalna metoda wymaga zainstalowanego zestawu narzędzi Swift. Otwórz Terminal i uruchom swift --version, aby to sprawdzić, zgodnie z opisem w przewodniku Wprowadzenie do Swift. W razie potrzeby Apple opisuje instalację narzędzi wiersza poleceń za pomocą polecenia xcode-select --install; przed kontynuacją dokończ instalację w wyświetlonym oknie. Zob. Instalowanie narzędzi wiersza poleceń.

Wklej cały poniższy blok do Terminala. Zawiera kompletny program i syntetyczne dane wejściowe. Parsuje znaczniki czasu z jawnym przesunięciem i bez ułamkowych sekund. Apple opisuje opcję .withInternetDateTime dla tego formatu znacznika czasu w dokumentacji opcji ISO8601DateFormatter.

swift - <<'SWIFT'
import Foundation

let zoneID = "America/New_York"
guard let zone = TimeZone(identifier: zoneID) else {
    fatalError("Unknown reporting zone: \(zoneID)")
}

var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = zone

let parser = ISO8601DateFormatter()
parser.formatOptions = [.withInternetDateTime]

let samples = [
    ("Spring", "2025-03-09T00:00:00-05:00",
               "2025-03-10T00:00:00-04:00"),
    ("Autumn", "2025-11-02T00:00:00-04:00",
               "2025-11-03T00:00:00-05:00")
]

for (label, startText, endText) in samples {
    guard let start = parser.date(from: startText),
          let end = parser.date(from: endText) else {
        fatalError("Could not parse timestamps for \(label)")
    }

    let startDay = calendar.startOfDay(for: start)
    let endDay = calendar.startOfDay(for: end)
    guard let days = calendar.dateComponents(
        [.day], from: startDay, to: endDay
    ).day else {
        fatalError("Could not calculate civil days for \(label)")
    }

    let hours = end.timeIntervalSince(start) / 3600
    print("\(label): \(days) civil day(s), \(hours) elapsed hours")
}
SWIFT

Oczekiwany wynik znajduje się poniżej. Przykłady liczbowe sprawdzono niezależnie za pomocą obliczeń dat; kod Swift został przeanalizowany, ale nie został tutaj uruchomiony w systemie macOS.

Wiosna: 1 dzień kalendarzowy, 23,0 godziny upływające
Jesień: 1 dzień kalendarzowy, 25,0 godzin upływających

Aby dostosować program, zastąp ciągi ze znacznikami czasu i świadomie wybierz strefę raportowania. Przesunięcia w znacznikach czasu określają konkretne momenty; strefa kalendarza wyznacza daty lokalne, na które te momenty przypadają. Program zatrzymuje się, jeśli parser zgłosi błąd, zamiast podstawiać bieżącą datę lub pomijać rekord.

Przykład obsługuje wskazany format ze znacznikiem przesunięcia. Ułamkowe sekundy wymagają innych opcji parsera. Program nie obsługuje też adnotacji stref w nawiasach kwadratowych z RFC 9557: przekaż nazwaną strefę osobno, jak pokazano, zamiast zakładać, że ta konfiguracja parsera obsługuje takie adnotacje.

Co sprawdzić, gdy wynik wygląda na błędny?

Wykonaj kolejno poniższe kontrole; każda dotyczy innego źródła rozbieżności.

  1. Potwierdź, jakiej liczby potrzebujesz. Różnica dat i liczba dat z wliczonymi krańcami różnią się o jeden w przypadku zakresu skierowanego w przyszłość.
  2. Potwierdź dane wejściowe. W przypadku publikacji opisanych samą datą użyj właściwego roku, miesiąca i dnia. Nie zakładaj, że zaimportowane znaczniki czasu już odpowiadają oczekiwanym datom lokalnym.
  3. Potwierdź strefę raportowania. Przelicz oba momenty w tej samej wybranej strefie, zanim wyodrębnisz daty.
  4. Potwierdź działanie. Po usunięciu wpływu pory dnia policz dni kalendarzowe. Dzielenie odstępu między momentami przez 86,400 odpowiada na pytanie o czas, który upłynął.
  5. Potwierdź kierunek. Zachowaj wynik ujemny, dopóki nie ustalisz, czy wcześniejszy i późniejszy wpis nie zostały zamienione miejscami.

W kodzie kalendarzowym używaj interfejsu początku dnia zamiast zakładać, że każdy dzień lokalny rozpoczyna się o jednoznacznej północy. Apple dokumentuje, że startOfDay(for:) wybiera pierwszą z dwóch północy albo pierwszy istniejący moment, jeśli północ nie występuje. Obsługuje to przypadek brzegowy, który może zostać pominięty przy ręcznym ustawieniu godziny na zero. Zob. startOfDay(for:).

Przykład Foundation obejmuje typowe zmiany czasu. W przypadku historycznych zmian, podczas których pominięto cały lokalny dzień, najpierw określ, czy zadanie polega na liczeniu dat kalendarza gregoriańskiego, czy lokalnych dni, które faktycznie istniały; to różne wymagania. Jeśli chodzi o pierwsze z nich, zachowuj daty podane jako daty kalendarzowe.

W arkuszu z datami publikacji końcowe obliczenie jest proste: ustal dwie właściwe daty gregoriańskie, zachowaj ich kolejność i użyj DAYS, aby obliczyć odstęp. Gdy dane wejściowe to konkretne momenty, przed obliczeniem jawnie określ strefę raportowania. Dzięki temu wynik będzie odnosić się do dat publikacji nawet wtedy, gdy w międzyczasie zmieni się czas.

Źródła