需求:將 XML 獲取的 ISO 8601 日期字符串 2009-11-23T05:24:41.000Z 轉換為用戶友好格式 Wed, Nov 4, 2009 8:00 PM。
NSString *xmlDateString = @"2009-11-23T05:24:41.000Z";
// 1. 解析輸入格式 (ISO 8601 / RFC 3339)
NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
inputFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSSZ"; // 注意 'T' 和 'Z' 轉義
inputFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; // 關鍵:固定區域,防止系統設置干擾
inputFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; // Z 表示 UTC
NSDate *date = [inputFormatter dateFromString:xmlDateString];
// 2. 格式化輸出格式
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
outputFormatter.dateFormat = @"EEE, MMM d, yyyy h:mm a"; // Wed, Nov 4, 2009 8:00 PM
outputFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; // 顯示語言
// outputFormatter.timeZone = [NSTimeZone localTimeZone]; // 默認本地時區,或指定
NSString *displayString = [outputFormatter stringFromDate:date];
NSLog(@"%@", displayString); // 輸出: Wed, Nov 23, 2009 5:24 AM (取決於時區轉換)
| 屬性 | 作用 | 注意 |
|---|---|---|
dateFormat | 定義解析/輸出模式 | 嚴格遵循 Unicode TR35 標準 |
locale | 控制月份/星期名稱語言 | 解析時必須用 en_US_POSIX,輸出按用戶語言 |
timeZone | 時區轉換 | 輸入 Z=UTC,輸出通常轉本地時區 |
lenient | 寬鬆解析 | 默認 YES,建議關閉嚴格匹配 |
en_US_POSIX,用戶地區設置為 24 小時制/非公曆會導致解析失敗或錯誤。YYYY (週年) vs yyyy (年),MM (月) vs mm (分)。Z 解析為 UTC,輸出默認本地時間。示例中 05:24 UTC 若在 UTC+8 顯示為 13:24。NSDateFormatter 創建開銷大,**靜態單例或緩存復用**
@available(iOS 10.0, *)
ISO8601DateFormatter *isoFormatter = [[ISO8601DateFormatter alloc] init];
isoFormatter.formatOptions = ISO8601DateFormatWithInternetDateTime | ISO8601DateFormatWithFractionalSeconds;
NSDate *date = [isoFormatter dateFromString:xmlDateString];
// 後續用 outputFormatter 格式化
專門處理 ISO 8601,更健壯、無需手寫格式字符串。
日期字符串轉換核心是兩步走:NSDateFormatter 解析為 NSDate(注意 en_US_POSIX locale),再格式化為目標字符串。掌握格式符號、Locale、TimeZone 三要素,可應對任意日期互轉需求。