Tampaknya NSDateFormatter
memiliki "fitur" yang menggigit Anda secara tak terduga: Jika Anda melakukan operasi format "tetap" sederhana seperti:
NSDateFormatter* fmt = [[NSDateFormatter alloc] init];
[fmt setDateFormat:@"yyyyMMddHHmmss"];
NSString* dateStr = [fmt stringFromDate:someDate];
[fmt release];
Kemudian berfungsi dengan baik di AS dan sebagian besar lokal SAMPAI ... seseorang dengan telepon mereka diatur ke wilayah 24 jam, menetapkan sakelar 12/24 jam di pengaturan menjadi 12. Kemudian yang di atas mulai menempelkan "AM" atau "PM" ke akhir string yang dihasilkan.
(Lihat, misalnya, NSDateFormatter, apakah saya melakukan sesuatu yang salah atau ini bug? )
(Dan lihat https://developer.apple.com/library/content/qa/qa1480/_index.html )
Rupanya Apple telah menyatakan ini sebagai "BURUK" - Rusak Seperti Dirancang, dan mereka tidak akan memperbaikinya.
Pengelakan ini tampaknya untuk mengatur lokal formatter tanggal untuk wilayah tertentu, umumnya AS, tetapi ini agak berantakan:
NSLocale *loc = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
[df setLocale: loc];
[loc release];
Tidak terlalu buruk dalam onsies-twosies, tapi saya berurusan dengan sekitar sepuluh aplikasi yang berbeda, dan yang pertama saya lihat memiliki 43 contoh skenario ini.
Jadi ada ide cerdas untuk kelas makro / yang ditimpa / apa pun untuk meminimalkan upaya untuk mengubah segalanya, tanpa membuat kode untuk mengaburkan? (Insting pertama saya adalah menimpa NSDateFormatter dengan versi yang akan mengatur lokal dalam metode init. Memerlukan perubahan dua baris - baris alokasi / init dan impor tambahan.)
Ditambahkan
Inilah yang saya buat sejauh ini - tampaknya bekerja di semua skenario:
@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
Karunia!
Saya akan memberikan hadiah untuk saran / kritik terbaik (sah) yang saya lihat pada pertengahan hari Selasa. [Lihat di bawah - batas waktu diperpanjang.]
Memperbarui
Proposal Re OMZ, inilah yang saya temukan -
Ini adalah versi kategori - file h:
#import <Foundation/Foundation.h>
@interface NSDateFormatter (Locale)
- (id)initWithSafeLocale;
@end
Kategori file 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
Kode:
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];
Hasil:
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)
Telepon [menjadikan iPod Touch] diatur ke Britania Raya, dengan sakelar 12/24 diatur ke 12. Ada perbedaan yang jelas dalam dua hasil, dan saya menilai versi kategorinya salah. Perhatikan bahwa log dalam versi kategori sedang dieksekusi (dan berhenti ditempatkan dalam kode dipukul), jadi itu bukan hanya kasus kode yang entah bagaimana tidak digunakan.
Pembaruan hadiah:
Karena saya belum mendapatkan balasan yang berlaku, namun saya akan memperpanjang batas waktu hadiah untuk satu atau dua hari lagi.
Bounty berakhir dalam 21 jam - itu akan jatuh ke siapa pun yang paling berusaha untuk membantu, bahkan jika jawabannya tidak benar-benar berguna dalam kasus saya.
Pengamatan yang aneh
Mengubah penerapan kategori sedikit:
#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
Pada dasarnya hanya mengubah nama variabel lokal statis (kalau-kalau ada beberapa konflik dengan statis dinyatakan dalam subkelas) dan menambahkan NSLog tambahan. Tapi lihat apa yang dicetak 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
Seperti yang Anda lihat, setLocale tidak. Lokal formatter masih en_GB. Tampaknya ada sesuatu yang "aneh" tentang metode init dalam suatu kategori.
Jawaban akhir
Lihat jawaban yang diterima di bawah ini.
- (NSDateFormatterBehavior)formatterBehavior
?