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ć:
- 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.
- Miesiąc i dzień są w niewłaściwej kolejności: sprawdź lokalizację przekazaną do formattera i upewnij się, czy bezpośrednio przypisano
dateFormatalbo ręcznie połączono ciągi. - Zmiana kolejności modyfikatorów nic nie daje: takie działanie jest zgodne z dokumentacją. Wybierz odpowiednią lokalizację zamiast zmieniać kolejność
.month()i.day(). - Wynik szablonu zachowuje wcześniejszą kolejność: ustaw nową lokalizację, a następnie ponownie utwórz format za pomocą
setLocalizedDateFormatFromTemplate. - 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
- Date.FormatStyle — Apple
- DateFormatter — Apple
- Unicode Technical Standard #35: Unicode Common Locale Data & Rules, Part 4: Dates — Unicode Consortium
- Date — Apple
- DateComponents — Apple
- TimeZone — Apple
- init(date:time:locale:calendar:timeZone:capitalizationContext:) — Apple
- setLocalizedDateFormatFromTemplate(_:) — Apple
- Install Swift — macOS — Swift.org
- ISO8601DateFormatter formatOptions — Apple
- RFC 3339: Date and Time on the Internet: Timestamps — RFC Editor
- RFC 9557: Date and Time on the Internet: Timestamps with Additional Information — RFC Editor