ดูเหมือนว่าNSDateFormatter
มี "คุณสมบัติ" ที่กัดคุณโดยไม่คาดคิด: หากคุณทำการดำเนินการรูปแบบ "คงที่" อย่างง่ายเช่น:
NSDateFormatter* fmt = [[NSDateFormatter alloc] init];
[fmt setDateFormat:@"yyyyMMddHHmmss"];
NSString* dateStr = [fmt stringFromDate:someDate];
[fmt release];
จากนั้นก็ใช้งานได้ดีในสหรัฐอเมริกาและตำแหน่งที่ตั้งส่วนใหญ่จนกระทั่ง ... ใครบางคนที่มีโทรศัพท์ตั้งค่าเป็น 24 ชั่วโมงตั้งค่าสวิตช์ 12/24 ชั่วโมงในการตั้งค่าเป็น 12 จากนั้นด้านบนจะเริ่มทำการตรึง "AM" หรือ "PM" จุดสิ้นสุดของสตริงผลลัพธ์
(ดู, เช่น, NSDateFormatter, ฉันกำลังทำอะไรผิดหรือเป็นบั๊ก? )
(และดูhttps://developer.apple.com/library/content/qa/qa1480/_index.html )
เห็นได้ชัดว่า Apple ประกาศว่า "BAD" ไม่ดีเท่าที่ออกแบบมาและพวกเขาจะไม่แก้ไข
การหลีกเลี่ยงนั้นดูเหมือนจะกำหนดสถานที่ของตัวจัดรูปแบบวันที่สำหรับภูมิภาคเฉพาะซึ่งโดยทั่วไปคือสหรัฐอเมริกา แต่นี่มันค่อนข้างยุ่งเหยิง:
NSLocale *loc = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
[df setLocale: loc];
[loc release];
ไม่เลวร้ายนักใน onsies-twosies แต่ฉันต้องจัดการกับแอพที่ต่างกันประมาณสิบแอพและแอพแรกที่ฉันดูมี 43 อินสแตนซ์ของสถานการณ์นี้
ดังนั้นความคิดที่ฉลาดสำหรับมาโคร / คลาสที่แทนที่ / อะไรก็ตามที่จะลดความพยายามในการเปลี่ยนแปลงทุกอย่างโดยไม่ทำให้โค้ดคลุมเครือ? (สัญชาตญาณแรกของฉันคือแทนที่ NSDateFormatter ด้วยเวอร์ชันที่จะตั้งค่าโลแคลในเมธอด init ต้องเปลี่ยนสองบรรทัด - บรรทัด alloc / init และการนำเข้าที่เพิ่ม)
ที่เพิ่ม
นี่คือสิ่งที่ฉันเกิดขึ้นจนถึงตอนนี้ดูเหมือนว่าจะใช้ได้ในทุกสถานการณ์:
@implementation BNSDateFormatter
-(id)init {
static NSLocale* en_US_POSIX = nil;
NSDateFormatter* me = [super init];
if (en_US_POSIX == nil) {
en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
}
[me setLocale:en_US_POSIX];
return me;
}
@end
เงินรางวัล!
ฉันจะมอบรางวัลให้กับคำแนะนำ / คำวิจารณ์ (ถูกกฎหมาย) ที่ดีที่สุดที่ฉันเห็นในช่วงกลางวันอังคาร [ดูด้านล่าง - ขยายกำหนดเวลา]
ปรับปรุง
ข้อเสนอของ OMZ อีกครั้งนี่คือสิ่งที่ฉันกำลังค้นหา -
นี่คือรุ่นหมวดหมู่ - ไฟล์ h:
#import <Foundation/Foundation.h>
@interface NSDateFormatter (Locale)
- (id)initWithSafeLocale;
@end
ไฟล์ประเภท m:
#import "NSDateFormatter+Locale.h"
@implementation NSDateFormatter (Locale)
- (id)initWithSafeLocale {
static NSLocale* en_US_POSIX = nil;
self = [super init];
if (en_US_POSIX == nil) {
en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
}
NSLog(@"Category's locale: %@ %@", en_US_POSIX.description, [en_US_POSIX localeIdentifier]);
[self setLocale:en_US_POSIX];
return self;
}
@end
รหัส:
NSDateFormatter* fmt;
NSString* dateString;
NSDate* date1;
NSDate* date2;
NSDate* date3;
NSDate* date4;
fmt = [[NSDateFormatter alloc] initWithSafeLocale];
[fmt setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
dateString = [fmt stringFromDate:[NSDate date]];
NSLog(@"dateString = %@", dateString);
date1 = [fmt dateFromString:@"2001-05-05 12:34:56"];
NSLog(@"date1 = %@", date1.description);
date2 = [fmt dateFromString:@"2001-05-05 22:34:56"];
NSLog(@"date2 = %@", date2.description);
date3 = [fmt dateFromString:@"2001-05-05 12:34:56PM"];
NSLog(@"date3 = %@", date3.description);
date4 = [fmt dateFromString:@"2001-05-05 12:34:56 PM"];
NSLog(@"date4 = %@", date4.description);
[fmt release];
fmt = [[BNSDateFormatter alloc] init];
[fmt setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
dateString = [fmt stringFromDate:[NSDate date]];
NSLog(@"dateString = %@", dateString);
date1 = [fmt dateFromString:@"2001-05-05 12:34:56"];
NSLog(@"date1 = %@", date1.description);
date2 = [fmt dateFromString:@"2001-05-05 22:34:56"];
NSLog(@"date2 = %@", date2.description);
date3 = [fmt dateFromString:@"2001-05-05 12:34:56PM"];
NSLog(@"date3 = %@", date3.description);
date4 = [fmt dateFromString:@"2001-05-05 12:34:56 PM"];
NSLog(@"date4 = %@", date4.description);
[fmt release];
ผลลัพธ์:
2011-07-11 17:44:43.243 DemoApp[160:307] Category's locale: <__NSCFLocale: 0x11a820> en_US_POSIX
2011-07-11 17:44:43.257 DemoApp[160:307] dateString = 2011-07-11 05:44:43 PM
2011-07-11 17:44:43.264 DemoApp[160:307] date1 = (null)
2011-07-11 17:44:43.272 DemoApp[160:307] date2 = (null)
2011-07-11 17:44:43.280 DemoApp[160:307] date3 = (null)
2011-07-11 17:44:43.298 DemoApp[160:307] date4 = 2001-05-05 05:34:56 PM +0000
2011-07-11 17:44:43.311 DemoApp[160:307] Extended class's locale: <__NSCFLocale: 0x11a820> en_US_POSIX
2011-07-11 17:44:43.336 DemoApp[160:307] dateString = 2011-07-11 17:44:43
2011-07-11 17:44:43.352 DemoApp[160:307] date1 = 2001-05-05 05:34:56 PM +0000
2011-07-11 17:44:43.369 DemoApp[160:307] date2 = 2001-05-06 03:34:56 AM +0000
2011-07-11 17:44:43.380 DemoApp[160:307] date3 = (null)
2011-07-11 17:44:43.392 DemoApp[160:307] date4 = (null)
โทรศัพท์ [ทำให้ iPod Touch] ถูกตั้งค่าเป็นบริเตนใหญ่โดยตั้งสวิตช์ 12/24 เป็น 12 มีความแตกต่างอย่างชัดเจนในผลการค้นหาทั้งสองและฉันตัดสินว่าหมวดหมู่นั้นผิด โปรดทราบว่าการเข้าสู่ระบบในเวอร์ชันหมวดหมู่นั้นจะได้รับการดำเนินการ (และหยุดลงในโค้ดจะได้รับผลกระทบ) ดังนั้นจึงไม่ใช่เพียงกรณีของรหัสที่ไม่ได้ใช้งาน
การปรับปรุงค่าหัว:
เนื่องจากฉันยังไม่ได้รับคำตอบใด ๆ เลยฉันจะขยายกำหนดเวลารับรางวัลไปอีกหนึ่งหรือสองวัน
เงินรางวัลจะจบลงใน 21 ชั่วโมง - มันจะไปหาใครก็ตามที่พยายามอย่างที่สุดที่จะช่วยเหลือแม้ว่าคำตอบจะไม่เป็นประโยชน์ในกรณีของฉัน
การสังเกตอยากรู้อยากเห็น
ปรับใช้หมวดหมู่เล็กน้อย:
#import "NSDateFormatter+Locale.h"
@implementation NSDateFormatter (Locale)
- (id)initWithSafeLocale {
static NSLocale* en_US_POSIX2 = nil;
self = [super init];
if (en_US_POSIX2 == nil) {
en_US_POSIX2 = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
}
NSLog(@"Category's locale: %@ %@", en_US_POSIX2.description, [en_US_POSIX2 localeIdentifier]);
[self setLocale:en_US_POSIX2];
NSLog(@"Category's object: %@ and object's locale: %@ %@", self.description, self.locale.description, [self.locale localeIdentifier]);
return self;
}
@end
โดยทั่วไปเพียงแค่เปลี่ยนชื่อของตัวแปรสถานที่แบบคงที่ (ในกรณีที่มีความขัดแย้งบางอย่างกับคงที่ประกาศในคลาสย่อย) และเพิ่ม NSLog พิเศษ แต่ดูสิ่งที่ NSLog พิมพ์:
2011-07-15 16:35:24.322 DemoApp[214:307] Category's locale: <__NSCFLocale: 0x160550> en_US_POSIX
2011-07-15 16:35:24.338 DemoApp[214:307] Category's object: <NSDateFormatter: 0x160d90> and object's locale: <__NSCFLocale: 0x12be70> en_GB
2011-07-15 16:35:24.345 DemoApp[214:307] dateString = 2011-07-15 04:35:24 PM
2011-07-15 16:35:24.370 DemoApp[214:307] date1 = (null)
2011-07-15 16:35:24.378 DemoApp[214:307] date2 = (null)
2011-07-15 16:35:24.390 DemoApp[214:307] date3 = (null)
2011-07-15 16:35:24.404 DemoApp[214:307] date4 = 2001-05-05 05:34:56 PM +0000
อย่างที่คุณเห็น setLocale ทำไม่ได้ โลแคลของตัวจัดรูปแบบยังคงเป็น en_GB ปรากฏว่ามีบางสิ่งที่ "แปลก" เกี่ยวกับวิธีการเริ่มต้นในหมวดหมู่
คำตอบสุดท้าย
ดูคำตอบที่ยอมรับด้านล่าง
- (NSDateFormatterBehavior)formatterBehavior
หรือไม่?