Macで月日だけの公開日ラベルを作成するには、SwiftのFoundationフォーマッターにその2つのフィールドを指定し、ロケールに順序を決めてもらいます。まず、入力が暦日なのかタイムスタンプなのかを判断してください。表示される日付をタイムゾーンによって変えるべきかどうかは、それによって決まります。

このガイドでは、合成した日付から公開日ラベルを生成する小さなTerminalスクリプトを紹介します。主な処理にはDate.FormatStyleを使い、既存のDateFormatterコード向けにテンプレートを使う方法も示します。Appleは、ローカライズされた日付出力の両方の方法を説明しています。Date.FormatStyle、DateFormatter

完成したパターンではなく、フィールドとして月と日を指定する

MMMM dのようなパターンでは、月が日より先に固定されます。ローカライズされたフィールド指定では、含める項目を指定しつつ、並び順はフォーマッターに任せます。Swiftで使う式はDate.FormatStyle().month(.wide).day()です。Appleは、書式指定子の順序を変えても、結果の文字列には影響しないと明記しています。そのため、先に.day()を呼び出しても、日が先に来る出力にはなりません。Date.FormatStyle

合成した公開日である2026年11月12日の場合、en_USを使うとNovember 12、en_GBを使うと12 Novemberのようなラベルになります。これらは明示的に指定したロケールのプレビューです。実行スクリプトでは、Macの現在のロケールを使ったラベルも出力します。Appleは、ローカライズされたテンプレートAPIでも、月と日の順序に同じ違いが生じる例を示しています。DateFormatter

Unicodeは、日付スケルトンを使ってこの違いを説明しています。日付スケルトンには、要求するフィールドとその長さが含まれ、ソフトウェアは適切なローカライズ済みパターンと照合します。たとえばMMMdは、省略形の月と日を要求します。スラッシュ、空白、最終的な表示順は指定しません。APIを問わず活用できる原則は、表示する要素を選び、ラベルの組み立てはフォーマッターに任せることです。Unicode Technical Standard #35, Part 4: Dates

公開日が何を表しているかを判断する

書式を設定する前に、以下の適切な行を選んでください。この判断によって、正しいフォーマッターを使っていても意図しない暦日が表示される事態を防げます。

入力 意味 書式設定の判断
年2026、月11、日12 暦日。指定された暦上の1日 これらのフィールドを維持する。Dateを介して変換する場合は、一貫した暦とタイムゾーンを使う
2026-11-12T00:30:00Z ある時点を表すタイムスタンプ その時点を解析し、表示に使うタイムゾーンを選ぶ
+02:00 UTCからの数値オフセット 現地時刻のタイムスタンプをUTCと対応付けるには十分だが、名前付きタイムゾーンは特定しない
Europe/London 名前付きタイムゾーン識別子 表示する時点に適用される規則を使う

Appleによると、Dateは暦やタイムゾーンに依存しない時点です。DateComponentsには、暦とタイムゾーンを使って評価する年、月、日などのフィールドが格納されます。そのため、日付だけの公開記録をDateを書式設定するAPIに渡す場合は、明示的な変換規則が必要です。Date、DateComponents

このタスクでは、規則は簡単です。元の年、月、日を維持し、UTCの正午にグレゴリオ暦の日付を作成して、同じ暦とUTCゾーンを使って書式設定します。正午は、この例で選んだ基準時刻にすぎません。日付を維持するのは、作成時と書式設定時の設定をそろえることです。この基準時刻は、実際の公開時刻を示すものではありません。

実際のタイムスタンプの場合は、代わりに意図した表示ゾーンを選んでください。ロケールは表示形式を決めますが、タイムスタンプに適用するゾーンは指定しません。名前付きゾーンでは時点によってオフセットが異なることがありますが、固定の数値オフセットにはそのような規則がありません。Appleは、タイムゾーン識別子と、日付に応じたオフセット取得の両方を提供しています。RFC 3339はタイムスタンプのオフセットを定義し、RFC 9557はタイムゾーンなどの追加情報を含められるよう、その表現を拡張しています。TimeZone、RFC 3339、RFC 9557

Terminalで月日フォーマッターを実行する

SwiftツールチェーンとmacOS SDKが利用できるmacOS 12以降を使ってください。Appleの説明によると、ここで使うDate.FormatStyleのイニシャライザーはmacOS 12以降で利用できます。Swift公式インストールページには、Appleプラットフォーム向け開発で使うXcodeを含め、Macのセットアップ手順が記載されています。Format-style initializer、Install Swift — macOS

以下の完全なプログラムを、プレーンテキストエディターでMonthDay.swiftとして保存します。合成したサンプルデータを含み、暦フィールドを検証し、現在のロケールと明示的に指定したロケールのプレビューを出力します。また、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()

Terminalを開き、ファイルがあるフォルダーに移動して、swift MonthDay.swiftを実行します。Swiftツールチェーンが利用できない場合は、続行する前にMac向けの公式インストール手順を完了してください。この例はドキュメントと照らし合わせて確認しましたが、調査環境ではSwiftを利用できなかったため実行していません。

2つの明示的なプレビューでは、同じ11月12日の日付が、月を先にするラベルと日を先にするラベルで表示されるはずです。現在のロケールの行は、Macの現在のロケール設定に従います。どちらのフォーマッターも、年や時刻を付けずに、月の完全な名称と日を指定します。出力はローカライズされた表示テキストとして扱い、後続処理を特定の空白文字や句読点に依存させないでください。Unicodeのパターン照合モデルでは、ロケールに応じた並び順が認められています。Unicode Technical Standard #35, Part 4: Dates

このプログラムでグレゴリオ暦を使うのは意図的です。合成した元のフィールドがその暦で定義されているためです。ロケールを変えて表示形式を変える間も、暦は固定されています。元の日付に別の暦が使われている場合は、表示方法を決める前に、その暦を使ってフィールドを解釈してください。Appleのイニシャライザーでは、この目的のためにロケール、暦、タイムゾーンを個別に指定できます。Format-style initializer

既存のDateFormatterコードでローカライズされたテンプレートを使う

プログラムの2つ目の方法では、setLocalizedDateFormatFromTemplate("MMMMd")を使います。ここで、MMMMは月の完全な名称を、dは月の日付を要求します。この文字列はローカライズ用メソッドに渡すテンプレートであり、最終的なdateFormatとして直接設定するものではありません。Apple自身の例でも、このテンプレートを使って月日を異なる順序で表示しています。DateFormatter

テンプレートメソッドを呼び出す前にlocaleを設定してください。Appleは、メソッドがその時点でフォーマッターに設定されているロケールを使って書式を決めるため、この順序を明示的に求めています。後から別のロケールを選んだ場合は、テンプレートメソッドをもう一度呼び出してください。この例ではプレビューごとに新しいフォーマッターを作成して、その依存関係が分かるようにしています。setLocalizedDateFormatFromTemplate(_:)

このラベル作成では、既存のコードに合う方を選んでください。最新のSwift APIではフィールド修飾子を使い、DateFormatterを使うワークフローではローカライズされたテンプレートメソッドを使います。月と日を別々に書式設定し、独自の区切り文字で組み合わせるのは避けてください。そうすると、並び順を決める役割が日付フォーマッターから離れてしまいます。

意図せずタスクを変えないようタイムスタンプを扱う

入力が合成タイムスタンプ2026-11-12T00:30:00Zだったとします。これはある時点を表します。同じ時点をオフセット+00:00で表示すると11月12日になり、オフセット-02:00で表示すると11月11日の22:30になります。これはオフセット計算の例であり、実際の公開イベントを示すものではありません。RFC 3339は、数値オフセットを現地時刻からUTCを引いた値として定義しています。RFC 3339, section 4.2

このような入力は、実際の表現に合わせて設定したISO 8601 APIで解析し、得られた時点を選択した表示ゾーンで書式設定してください。Appleは、RFC 3339形式の日付と時刻の文字列に対して、ISO8601DateFormatterとその.withInternetDateTimeオプションを説明しています。このオプションは解析設定であり、ローカライズされた月日表示の指定とは別です。ISO8601DateFormatter formatOptions

変換規則を意図的に定めていない限り、暦日しか指定されていない入力にこのタイムスタンプ用の手順を適用しないでください。同様に、Zのサフィックスが公開日の名前付きタイムゾーンを特定すると考えないでください。RFC 9557では、名前付きゾーン情報は基本的なタイムスタンプ表現に加える追加情報として扱われます。RFC 9557

想定外のラベルを適切な順序で診断する

どの判断を変更すべきか、次の順序で確認してください。

  1. 日付が違う: 入力が暦日か時点かを確認します。暦日用プログラムでは、作成時と書式設定時の両方でUTCを使います。時点の場合は、意図した表示ゾーンを確認します。
  2. 月と日の順序が違う: フォーマッターに渡したロケールを確認し、dateFormatを直接設定していないか、文字列を手作業で連結していないかを調べます。
  3. 修飾子の順序を変えても変化がない: これは仕様に記載された動作です。.month()と.day()の順序を入れ替えるのではなく、適切なロケールを選んでください。
  4. テンプレート出力に以前の並び順が残る: 新しいロケールを設定してから、setLocalizedDateFormatFromTemplateで書式を再生成します。
  5. 元のフィールドが無効: 入力を報告するか修正します。完全なプログラムでは、別の公開日に置き換えず、変換前に入力の有効性を確認します。

これらの確認は、時点、その暦上の解釈、ローカライズされた表示がそれぞれ別であるという、ドキュメント上の区別に沿っています。Appleは、修飾子の順序に依存しないこと、テンプレートの設定順序、日付コンポーネントの検証について、該当するAPIで説明しています。Date.FormatStyle、setLocalizedDateFormatFromTemplate(_:)、DateComponents

ラベルを作成した後も、完全な元の日付またはタイムスタンプは保持してください。月日だけの文字列では年が省略され、タイムスタンプを整形したラベルでも時刻とタイムゾーンが省略されるため、表示文字列だけでは入力全体を保持できません。信頼できる公開日ラベルを作るには、元の値を保持し、暦とゾーンを意図的に選び、要求した月と日の並び順はロケールに任せてください。

参考資料