Aby utworzyć na Macu etykietę publikacji zawierającą miesiąc i dzień, zażądaj tych dwóch pól za pomocą formattera Foundation w Swift i pozwól lokalizacji ustalić ich kolejność. Najpierw zdecyduj, czy dane wejściowe to data kalendarzowa, czy znacznik czasu: od tego zależy, czy strefa czasowa powinna zmieniać wyświetlany dzień.

Ten przewodnik pokazuje krótki skrypt Terminala, który tworzy etykiety publikacji na podstawie przykładowych dat. Do głównej operacji używa Date.FormatStyle i przedstawia alternatywę opartą na szablonie dla istniejącego kodu DateFormatter. Apple dokumentuje oba podejścia do lokalizowanego wyświetlania dat. Date.FormatStyle, DateFormatter

Żądaj miesiąca i dnia jako pól, a nie gotowego wzorca

Wzorzec taki jak MMMM d ustala kolejność: najpierw miesiąc, potem dzień. Zlokalizowane żądanie pól określa, co uwzględnić, pozostawiając formatterowi ustalenie kolejności. W Swift odpowiednie wyrażenie to Date.FormatStyle().month(.wide).day(). Apple wyraźnie stwierdza, że kolejność modyfikatorów formatowania nie wpływa na wynikowy ciąg. Dlatego wywołanie najpierw .day() nie wymusza formatu z dniem na początku. Date.FormatStyle

Dla przykładowej daty publikacji 12 listopada 2026 r. ilustracyjne etykiety to November 12 z en_US oraz 12 November z en_GB. Są to jawnie określone lokalizacje podglądu; działający skrypt wypisuje też etykietę zgodną z bieżącą lokalizacją Maca. Apple pokazuje tę samą różnicę w kolejności miesiąca i dnia za pomocą zlokalizowanego interfejsu API szablonów. DateFormatter

Unicode opisuje tę różnicę za pomocą szkieletów dat: zawierają one żądane pola i długości pól, a oprogramowanie dopasowuje je do odpowiedniego zlokalizowanego wzorca. Na przykład MMMd oznacza skróconą nazwę miesiąca i dzień. Nie określa separatora, spacji ani końcowej kolejności wyświetlania. To przydatna zasada, którą można przenosić między interfejsami API: wybierz składniki, a następnie pozwól formatterowi złożyć etykietę. Unicode Technical Standard #35, Part 4: Dates

Zdecyduj, co oznacza data publikacji

Przed formatowaniem wybierz odpowiedni wiersz poniżej. Ta decyzja zapobiega wyświetleniu przez poprawnie działający formatter niezamierzonego dnia kalendarzowego.

Dane wejściowe Znaczenie Decyzja dotycząca formatowania
Rok 2026, miesiąc 11, dzień 12 Data cywilna: jeden dzień w określonym kalendarzu Zachowaj te pola; podczas konwersji przez Date używaj spójnego kalendarza i strefy czasowej
2026-11-12T00:30:00Z Znacznik czasu wskazujący konkretną chwilę Przeanalizuj tę chwilę, a następnie wybierz strefę czasową, w której ma być wyświetlana
+02:00 Przesunięcie liczbowe względem UTC Wystarcza do powiązania lokalnego znacznika czasu z UTC, ale nie identyfikuje nazwanej strefy
Europe/London Identyfikator nazwanej strefy czasowej Zastosuj jej reguły do wyświetlanej chwili

Apple definiuje Date jako punkt w czasie niezależny od kalendarza i strefy czasowej. DateComponents przechowuje pola takie jak rok, miesiąc i dzień, które są interpretowane z użyciem kalendarza i strefy czasowej. Dlatego rekord publikacji zawierający samą datę wymaga jawnie określonej konwencji konwersji, gdy przekazuje się go do interfejsu API formatującego Date. Date, DateComponents

Na potrzeby tego zadania konwencja jest prosta: zachowaj źródłowe wartości roku, miesiąca i dnia, utwórz datę gregoriańską w południe w strefie UTC i sformatuj ją z użyciem tego samego kalendarza i strefy UTC. Południe jest tu po prostu wybranym punktem odniesienia. Zachowanie spójności podczas tworzenia i formatowania pozwala zachować datę. Ten punkt odniesienia nie oznacza rzeczywistej godziny publikacji.

W przypadku prawdziwego znacznika czasu wybierz docelową strefę wyświetlania. Lokalizacja określa sposób prezentacji; nie wyznacza docelowej strefy znacznika czasu. Nazwana strefa może mieć różne przesunięcia w zależności od chwili, natomiast stałe przesunięcie liczbowe nie dostarcza takich reguł. Apple udostępnia zarówno identyfikatory stref, jak i operacje zwracające przesunięcie dla danej daty. RFC 3339 definiuje przesunięcia znaczników czasu, a RFC 9557 rozszerza ten zapis o dodatkowe informacje, w tym strefę czasową. TimeZone, RFC 3339, RFC 9557

Uruchom w Terminalu kompletny formatter miesiąca i dnia

Użyj systemu macOS 12 lub nowszego z zestawem narzędzi Swift i dostępnym pakietem SDK macOS. Apple dokumentuje użyty tu inicjalizator Date.FormatStyle jako dostępny od macOS 12. Oficjalna strona instalacji Swift zawiera instrukcje konfiguracji Maca, w tym instalację Xcode do tworzenia oprogramowania na platformy Apple. Format-style initializer, Install Swift — macOS

Zapisz poniższy kompletny program jako MonthDay.swift w edytorze zwykłego tekstu. Zawiera własne przykładowe dane, sprawdza poprawność pól kalendarza i wyświetla podglądy dla bieżącej oraz jawnie określonych lokalizacji. Wypisuje także równoważny wynik uzyskany na podstawie szablonu, aby można było porównać oba interfejsy API.

import Foundation

enum LabelError: Error {
    case unavailableUTC
    case invalidPublicationDate
}

func main() throws {
    guard let utc = TimeZone(secondsFromGMT: 0) else {
        throw LabelError.unavailableUTC
    }

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

    // Synthetic civil publication date, not an actual timestamp.
    var fields = DateComponents()
    fields.calendar = calendar
    fields.timeZone = utc
    fields.year = 2026
    fields.month = 11
    fields.day = 12
    fields.hour = 12

    guard fields.isValidDate(in: calendar),
          let publicationDate = calendar.date(from: fields) else {
        throw LabelError.invalidPublicationDate
    }

    let previews: [(String, Locale)] = [
        ("Current locale", .current),
        ("en_US", Locale(identifier: "en_US")),
        ("en_GB", Locale(identifier: "en_GB"))
    ]

    for (name, locale) in previews {
        let style = Date.FormatStyle(
            locale: locale,
            calendar: calendar,
            timeZone: utc
        )
        .month(.wide)
        .day()

        print("\(name): \(publicationDate.formatted(style))")

        let formatter = DateFormatter()
        formatter.locale = locale
        formatter.calendar = calendar
        formatter.timeZone = utc
        formatter.setLocalizedDateFormatFromTemplate("MMMMd")

        print("\(name), template: \(formatter.string(from: publicationDate))")
    }
}

try main()

Otwórz Terminal, przejdź do folderu zawierającego plik i uruchom swift MonthDay.swift. Jeśli zestaw narzędzi Swift nie jest dostępny, przed kontynuowaniem wykonaj oficjalne kroki instalacji na Macu. Przykład sprawdzono pod kątem zgodności z dokumentacją, ale nie uruchomiono go w tym środowisku badawczym, ponieważ Swift nie był dostępny.

Dwa jawne podglądy powinny pokazywać format z miesiącem na początku i z dniem na początku dla tej samej daty 12 listopada. Wiersz z bieżącą lokalizacją odzwierciedla ustawienie lokalizacji Twojego Maca. Obie ścieżki formatowania żądają pełnej nazwy miesiąca i dnia, bez roku ani godziny. Traktuj wynik jako zlokalizowany tekst do wyświetlania; unikaj uzależniania dalszego przetwarzania od konkretnej spacji lub znaku interpunkcyjnego. Model dopasowywania wzorców Unicode dopuszcza kolejność zależną od lokalizacji. Unicode Technical Standard #35, Part 4: Dates

Użycie kalendarza gregoriańskiego w tym programie jest celowe: źródłowe przykładowe pola są zdefiniowane w tym kalendarzu. Kalendarz pozostaje stały, podczas gdy lokalizacja zmienia sposób prezentacji. Jeśli daty źródłowe korzystają z innego kalendarza, zinterpretuj ich pola za pomocą tego kalendarza, zanim zdecydujesz, jak je wyświetlać. Inicjalizator Apple udostępnia osobne parametry dla lokalizacji, kalendarza i strefy czasowej. Format-style initializer

Użyj zlokalizowanego szablonu w istniejącym kodzie DateFormatter

Druga ścieżka w programie używa setLocalizedDateFormatFromTemplate("MMMMd"). Tutaj MMMM żąda pełnej nazwy miesiąca, a d — dnia miesiąca. Ciąg jest szablonem przekazywanym do metody lokalizującej; nie jest przypisywany bezpośrednio jako końcowy dateFormat. W swoim przykładzie Apple używa dokładnie tego szablonu, aby uzyskać różne kolejności miesiąca i dnia. DateFormatter

Ustaw locale przed wywołaniem metody szablonów. Apple wyraźnie wymaga tej kolejności, ponieważ metoda tworzy format z użyciem lokalizacji przypisanej do formattera w danym momencie. Jeśli później wybierzesz inną lokalizację, ponownie wywołaj metodę szablonów. Przykład tworzy nowy formatter dla każdego podglądu, aby uwidocznić tę zależność. setLocalizedDateFormatFromTemplate(_:)

W przypadku tej etykiety wybierz ścieżkę pasującą do istniejącego kodu: modyfikatory pól w nowoczesnym interfejsie API Swift albo metodę zlokalizowanych szablonów w rozwiązaniu opartym na DateFormatter. Unikaj składania osobno sformatowanych ciągów miesiąca i dnia za pomocą własnego separatora, ponieważ w ten sposób odbierasz formatterowi dat odpowiedzialność za ustalenie kolejności.

Obsłuż znaczniki czasu bez przypadkowej zmiany znaczenia zadania

Załóżmy, że źródło dostarcza zamiast tego przykładowy znacznik czasu 2026-11-12T00:30:00Z. Wskazuje on konkretną chwilę. Wyświetlenie jej przy przesunięciu +00:00 daje 12 listopada; wyświetlenie tej samej chwili przy przesunięciu -02:00 daje 11 listopada o 22:30. To przykładowe obliczenie przesunięcia, a nie zaobserwowane zdarzenie publikacji. RFC 3339 definiuje przesunięcia liczbowe jako różnicę między czasem lokalnym a UTC. RFC 3339, section 4.2

Przeanalizuj takie dane za pomocą interfejsu API ISO 8601 skonfigurowanego dla ich rzeczywistego formatu, a następnie sformatuj uzyskaną chwilę z wybraną strefą wyświetlania. Apple dokumentuje ISO8601DateFormatter i jego opcję .withInternetDateTime dla ciągów daty i czasu zgodnych z RFC 3339. Ta opcja konfiguruje analizowanie danych, niezależnie od zlokalizowanego żądania wyświetlenia miesiąca i dnia. ISO8601DateFormatter formatOptions

Nie stosuj tej obsługi znaczników czasu do źródła zawierającego wyłącznie datę cywilną, chyba że świadomie określono konwencję konwersji. Nie zakładaj też, że przyrostek Z wskazuje nazwaną strefę czasową publikacji. RFC 9557 traktuje informacje o nazwanej strefie jako dodatkowe względem podstawowego zapisu znacznika czasu. RFC 9557

Diagnozuj nieoczekiwaną etykietę we właściwej kolejności

Wykonaj poniższe kroki, aby ustalić, którą decyzję należy zmienić:

  1. Dzień jest nieprawidłowy: sprawdź, czy dane wejściowe to data cywilna, czy konkretna chwila. W programie obsługującym datę cywilną zachowaj UTC przy tworzeniu i formatowaniu. W przypadku konkretnej chwili sprawdź docelową strefę wyświetlania.
  2. Miesiąc i dzień są w niewłaściwej kolejności: sprawdź lokalizację przekazaną do formattera i upewnij się, czy bezpośrednio przypisano dateFormat albo ręcznie połączono ciągi.
  3. Zmiana kolejności modyfikatorów nic nie daje: takie działanie jest zgodne z dokumentacją. Wybierz odpowiednią lokalizację zamiast zmieniać kolejność .month() i .day().
  4. Wynik szablonu zachowuje wcześniejszą kolejność: ustaw nową lokalizację, a następnie ponownie utwórz format za pomocą setLocalizedDateFormatFromTemplate.
  5. Pola źródłowe są nieprawidłowe: zgłoś lub popraw dane wejściowe. Kompletny program sprawdza poprawność przed konwersją, zamiast zastępować datę inną datą publikacji.

Kontrole te odzwierciedlają udokumentowany podział na konkretną chwilę, jej interpretację kalendarzową i zlokalizowaną prezentację. Apple dokumentuje niezależność od kolejności modyfikatorów, kolejność konfiguracji szablonu i sprawdzanie poprawności składników daty w odpowiednich interfejsach API. Date.FormatStyle, setLocalizedDateFormatFromTemplate(_:), DateComponents

Zachowaj pełną datę źródłową lub znacznik czasu po utworzeniu etykiety. Ciąg zawierający tylko miesiąc i dzień celowo pomija rok, a sformatowana etykieta znacznika czasu pomija też godzinę i strefę; sam tekst wyświetlany nie zachowuje pełnych danych wejściowych. Aby utworzyć niezawodną etykietę publikacji, zachowaj wartość źródłową, świadomie wybierz kalendarz i strefę, a ustalenie kolejności miesiąca i dnia powierz lokalizacji.

Źródła