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 참조 )
분명히 애플은 이것을 "BAD"라고 선언했다-Broken As Designed, 그들은 그것을 고치지 않을 것이다.
우회는 분명히 특정 지역, 일반적으로 미국에 대한 날짜 형식 기의 로캘을 설정하는 것이지만 약간 지저분합니다.
NSLocale *loc = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
[df setLocale: loc];
[loc release];
onsies-twosies에서 나쁘지는 않지만 약 10 개의 다른 앱을 다루고 있으며, 내가 본 첫 번째 앱에는이 시나리오의 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
하사품!
화요일 정오까지 볼 수있는 최고의 (합법적 인) 제안 / 비평에 바운티를 수여합니다. [아래 참조-기한 연장]
최신 정보
Re 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)
12/24 스위치가 12로 설정된 전화기 [iPod Touch로 확인]가 영국으로 설정되어 있습니다. 두 결과에 분명한 차이가 있으며 범주 버전이 잘못되었다고 판단합니다. 범주 버전의 로그가 실행되고 있으며 코드에 배치 된 중지가 발생 했으므로 코드가 사용되지 않는 경우가 아닙니다.
현상금 업데이트 :
해당 답변을받지 못했지만 바운티 마감일을 하루나 이틀 더 연장 할 것입니다.
바운티는 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입니다. 카테고리의 init 메소드에 대해 "이상한"것이있는 것 같습니다.
최종 답변
아래에서 허용되는 답변을 참조하십시오 .
- (NSDateFormatterBehavior)formatterBehavior
했습니까?