表示完整的一天時,包含當天起始時間,並排除隔天的起始時間。若要在 Mac 行事曆中建立出版日期標記,請建立全天事件;在 iCalendar 資料中,明確的結束日期代表事件範圍外的第一天。
本指南使用一個虛構的出版日期:2027 年 6 月 18 日。任務是在 Mac 行事曆中標記完整的出版日、匯出事件,並檢查其邊界。當日期在行事曆、試算表與自動化流程之間傳遞時,這套推理方式也能幫助你辨認錯誤。
排除式次日邊界是什麼意思?
對這個虛構的出版日而言,納入的日期是 6 月 18 日。6 月 19 日是排除範圍外的第一天。以半開區間表示為 [2027-06-18, 2027-06-19):方括號表示包含起點,圓括號表示不包含終點。
iCalendar 標準規定,事件的 DTSTART 為包含端點,而 DTEND 不包含端點。全天事件的起訖值都使用日期。因此,將結束日期設為隔天,就表示完整的一天。僅含日期的值不得帶有 TZID 參數。RFC 5545,事件元件與時區識別碼。
以下示意片段只顯示兩個邊界屬性,並非可完整匯入的行事曆檔案:
DTSTART;VALUE=DATE:20270618
DTEND;VALUE=DATE:20270619
下方的決策表將這項規則套用於虛構的出版排程。請將最後一欄視為排除範圍外的第一天,而不是另一個出版日。
| 預定涵蓋範圍 | 納入的開始日期 | 排除式結束日期 |
|---|---|---|
| 僅 6 月 18 日 | 2027 年 6 月 18 日 | 2027 年 6 月 19 日 |
| 包含 6 月 18 日至 20 日 | 2027 年 6 月 18 日 | 2027 年 6 月 21 日 |
| 僅 6 月 30 日 | 2027 年 6 月 30 日 | 2027 年 7 月 1 日 |
在 Mac 行事曆中建立出版日
先使用一個可建立事件的行事曆。這項操作需要行事曆的全天事件控制項,不需要任何程式工具。
- 開啟行事曆並前往 2027 年 6 月 18 日。
- 在視窗頂端選取
日或週。 - 在 6 月 18 日的小時格上方,連按兩下
all-day區域。 - 將事件命名為中性的「Sample publication day」。
- 確認標記只占據 6 月 18 日。
Apple 說明,可以在「日」或「週」檢視中連按兩下全天區域來建立全天事件;另外也說明可拖曳跨越日期來建立多日事件。此範例請使用建立單日事件的方式。在 Mac 上的行事曆中設定全天、多日或重複事件。
先以行事曆上的可見內容進行檢查:標記應涵蓋預定日期,不應延伸到 6 月 19 日。排除式邊界描述的是資料中的範圍表示方式,並不表示要將可見標記延伸到隔天。
匯出事件並檢查日期邊界
在行事曆列表中選取該事件所在的行事曆,然後選擇 檔案 > 匯出 > 匯出。將產生的 .ics 檔案儲存在方便的位置。此操作會匯出所選行事曆中的事件,因此,若該行事曆包含多個事件,產生的檔案也會包含多筆事件紀錄。Apple 說明此匯出使用 .ics 格式。在 Mac 上匯入或匯出行事曆。
在 Finder 中選取匯出的檔案,並使用 檔案 > 打開方式,以 TextEdit 等文字編輯器開啟。Apple 說明這是為單次開啟檔案選擇應用程式的方法。在 Mac 上選擇用來開啟檔案的 App。
找到 Sample publication day,然後檢視其周圍的事件紀錄。將其中的開始與結束屬性和上方的示意片段比較。預期會出現其他屬性;請著重檢查日期值及其類型。
如果全天事件既沒有 DTEND,也沒有 DURATION,標準會將其時長設為一天。因此,缺少明確的結束時間本身不一定表示有問題。RFC 5545,事件元件。
將匯出檔視為診斷用副本。如果可見事件涵蓋了錯誤的日期,請在行事曆中修正後再次匯出。這樣檢查的對象就會是你實際建立的事件。
區分民用日期、時間點、時差與命名時區
將出版日移至其他工具之前,先確認該工具需要哪一種值。行事曆日期標籤與時間戳記回答的是不同問題。
| 概念 | 示意值 | 所代表的意義 |
|---|---|---|
| 民用日期 | 2027-06-18 |
不含時刻的行事曆日期 |
| 時間點 | 2027-06-18T10:00:00Z |
時間軸上的一個點 |
| 數字 UTC 時差 | +02:00 |
當地時間與 UTC 的時差 |
| 命名時區 | Europe/Paris |
其規則決定適用時差的時區 |
RFC 3339 定義了時間點的時間戳記表示方式,其中包括數字時差與 UTC 標記 Z。它明確指出,區間描述不在其範圍內。因此,一對 RFC 3339 時間戳記仍須另行約定端點是否納入。RFC 3339,範圍與日期/時間格式。
例如,虛構的時間戳記 2027-06-18T12:00:00+02:00 與 2027-06-18T10:00:00Z 指的是同一個時間點。兩者都不代表完整的出版日。為日期加上時間和時差,會改變你記錄的資訊。RFC 3339,當地時差。
命名時區提供計算當地時間與適用時差的規則。IANA 維護這些規則,包括時差與日光節約時間行為的變更;作業系統與軟體供應商會將更新提供給使用者。計算不同日期的邊界時,單一數字時差無法取代這套規則。IANA 時區。
對於行事曆標記,請保留民用日期。如果後續任務要找出哪些帶時間戳記的出版項目屬於該日,請先選定用來定義出版日的命名時區,再於該時區中計算兩個邊界時間點。
Mac 自動化如何計算相同範圍?
Apple 的 Foundation Date 表示一個不依賴行事曆或時區的時間點。若你的輸入只有 6 月 18 日,這個名稱可能會造成誤解:民用日期必須有行事曆背景,才能對應到某個時間點。Apple 建議使用 Calendar 進行行事曆運算。Date。
在自動化流程中,請明確指定行事曆系統與時區。Foundation 透過行事曆可寫入的 timeZone 屬性提供其時區。明確設定這項選擇,就能讓維護自動化流程的人看出預定的出版日定義。Calendar.timeZone。
給定一個已知落在預定日期內的時間點,Calendar.dateInterval(of: .day, for:) 會取得該行事曆元件的起始時間與時長。此方法回傳可選值;自動化流程必須處理失敗情況,而不是默默改用其他日期。dateInterval(of:for:)。
有一個重要的端點細節:Apple 將 DateInterval 定義為包含兩個端點的閉區間。若要實作排除式的出版日邊界,請使用計算出的邊界並明確比較:start <= instant && instant < end。這是成員判定規則,並非完整程式。DateInterval。
請勿假設每個當地日期都從一般的午夜開始。Apple 的 startOfDay(for:) 會回傳該日第一個存在的時刻:若有兩個午夜,便選第一個;若午夜不存在,則選第一個存在的時刻。以行事曆計算出的邊界會保留這項差異。startOfDay(for:)。
重用日期前先檢查邊界
對於以時間戳記為基礎的工作流程,請對計算出的範圍執行以下三項驗收檢查。這些預期結果直接來自明確採用排除式結束邊界的比較方式。
| 測試時間點 | 預期是否納入 |
|---|---|
| 恰好是當天起始時間 | 納入 |
| 嚴格位於兩個邊界之間的任意時間點 | 納入 |
| 恰好是隔天起始時間 | 排除 |
這項檢查也說明,為何不需要捏造像 23:59:59 這樣的最後時刻。如果輸入包含小數秒,晚於該截止時間的值仍可能早於隔天的邊界。直接與排除式邊界比較,就不必為「最後一刻」選定時間戳記精度。
若要完成 Mac 桌面操作,最後請確認 Sample publication day 只占據 6 月 18 日,且匯出的日期表示方式符合這項涵蓋範圍。之後若將此日期用作時間戳記篩選條件,請保留選定的行事曆與時區,納入起點並排除隔天的邊界。
來源
在 Mac 上的行事曆中設定全天、多日或重複事件 — Apple。
在 Mac 上匯入或匯出行事曆 — Apple。
在 Mac 上選擇用來開啟檔案的 App — Apple。
RFC 5545:網際網路行事曆與排程核心物件規範(iCalendar) — RFC Editor。
RFC 3339:網際網路上的日期與時間:時間戳記 — RFC Editor。
時區 — IANA。
Date — Apple 開發者文件。
timeZone — Apple 開發者文件。
dateInterval(of:for:) — Apple 開發者文件。
DateInterval — Apple 開發者文件。
startOfDay(for:) — Apple 開發者文件。