بهترین راه برای مقابله با محلی "feechur" NSDateFormatter چیست؟

به نظر می رسد که 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 ]

ظاهراً اپل این را "بد" اعلام کرده است - همانطور که طراحی شده شکسته است ، و آنها قصد ندارند آن را برطرف کنند.

ظاهراً این دور زدن به محلی از قالب ساز تاریخ را برای یک منطقه خاص ، به طور کلی ایالات متحده تنظیم کنید ، اما این کمی ناخوشایند است:

NSLocale *loc = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
[df setLocale: loc];
[loc release];

در onsies-twosies خیلی بد نیست ، اما من با حدود ده برنامه مختلف سر و کار دارم ، و اولین برنامه من look at 43 نمونه از این سناریو را دارد

بنابراین ، ایده های هوشمندانه ای برای یک کلاس کلان / غلبه بر هر چیز / برای به حداقل رساندن تلاش برای تغییر همه چیز ، بدون ایجاد کد برای مبهم بودن؟ (اولین غریزه من نادیده گرفتن NSDateFormatter با نسخه ای است که محلی را در روش 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

فضل!

من به بهترین پیشنهاد / انتقاد (قانونی) که تا اواسط روز سه شنبه می بینم پاداش می دهم. [به زیر مراجعه کنید - مهلت تمدید شده است.]

به روزرسانی

پیشنهاد Re OMZ ، این چیزی است که من پیدا می کنم -

در اینجا نسخه دسته وجود دارد - پرونده h:

#import 


@interface NSDateFormatter (Locale)
- (id)initWithSafeLocale;
@end

پرونده m 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 تنظیم شده است. تفاوت آشکاری در دو نتیجه وجود دارد ، و من نسخه دسته را اشتباه ارزیابی کنید. توجه داشته باشید که ورود به سیستم در نسخه دسته اجرا می شود (و توقف هایی که در کد قرار می گیرد ضربه می خورد) ، بنابراین این فقط به این دلیل نیست که کد به نحوی مورد استفاده قرار نمی گیرد.

به روزرسانی Bounty:

از آنجا که من این کار را نکرده ام پاسخ قابل قبولی دریافت کرده اید اما مهلت پاداش را برای یکی دو روز دیگر تمدید می کنم.

Bounty در 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:  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 است. به نظر می رسد که چیزی "عجیب" در مورد روش init در یک گروه وجود دارد.

پاسخ نهایی

به پاسخ پذیرفته شده در زیر مراجعه کنید.

164
задан Cœur 28 June 2017 в 14:49
поделиться