在某些地区,如en_US,日历应用程序显示短(3个字母)的月份名称.
在其他语言环境(例如de_DE)下,日历应用程序会显示完整的月份名称.有趣的是,语言环境en_DE显示了短的月份名称,因此它似乎与区域格式的语言相关联.
我不知道的是如何知道使用哪个月份格式.
不管我的设备的区域设置,NSDateFormatter独立的ShortMonthSymbols给了我3个字母的月份名称,NSDateFormatter standaloneMonthSymbols给了我完整的月份名称.
也试过:
NSString *monthformat = [NSDateFormatter dateFormatFromTemplate:@"LLL" options:0 locale:[NSLocale currentLocale]];
并且为en_US和de_DE返回相同的LLL.
看NSLocale,似乎没有任何价值决定是使用短名称还是全名.
NSCalendar,NSDateFormatter或NSLocale中似乎没有什么可以帮助确定要使用哪个月份格式.
有谁有任何想法如何做出这样的决心?
更新:
我以为我找到了一个解决方案,但它并不适用于我尝试的所有地区.我使用各种语言环境运行以下代码,以查看是否可以在本地应用程序中显示短和长的月份名称的区域设置之间找到任何共同点:
NSLocale *locale = [NSLocale currentLocale]; NSString *locid = [locale localeIdentifier]; NSLog(@"Locale = %@",locid); NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; NSLog(@"monthSymbols = %@",[formatter monthSymbols]); NSLog(@"shortMonthSymbols = %@",[formatter shortMonthSymbols]); NSLog(@"veryShortMonthSymbols = %@",[formatter veryShortMonthSymbols]); NSLog(@"monthStandaloneSymbols = %@",[formatter standaloneMonthSymbols]); NSLog(@"shortStandaloneMonthSymbols = %@",[formatter shortStandaloneMonthSymbols]); NSLog(@"veryShortStandaloneMonthSymbols = %@",[formatter veryShortStandaloneMonthSymbols]); NSDate *date = [NSDate date]; [formatter setDateStyle:NSDateFormatterShortStyle]; NSLog(@"short date style: %@",[formatter stringFromDate:date]); [formatter setDateStyle:NSDateFormatterMediumStyle]; NSLog(@"medium date style: %@",[formatter stringFromDate:date]); [formatter setDateStyle:NSDateFormatterLongStyle]; NSLog(@"long date style: %@",[formatter stringFromDate:date]); [formatter setDateStyle:NSDateFormatterFullStyle]; NSLog(@"full date style: %@",[formatter stringFromDate:date]); [formatter setDateStyle:NSDateFormatterNoStyle]; [formatter setDateFormat:@"M"]; NSLog(@"M date format: %@",[formatter stringFromDate:date]); [formatter setDateFormat:@"MM"]; NSLog(@"MM date format: %@",[formatter stringFromDate:date]); [formatter setDateFormat:@"MMM"]; NSLog(@"MMM date format: %@",[formatter stringFromDate:date]); [formatter setDateFormat:@"MMMM"]; NSLog(@"MMMM date format: %@",[formatter stringFromDate:date]); [formatter setDateFormat:@"MMMMM"]; NSLog(@"MMMMM date format: %@",[formatter stringFromDate:date]); [formatter setDateFormat:@"L"]; NSLog(@"L date format: %@",[formatter stringFromDate:date]); [formatter setDateFormat:@"LL"]; NSLog(@"LL date format: %@",[formatter stringFromDate:date]); [formatter setDateFormat:@"LLL"]; NSLog(@"LLL date format: %@",[formatter stringFromDate:date]); [formatter setDateFormat:@"LLLL"]; NSLog(@"LLLL date format: %@",[formatter stringFromDate:date]); [formatter setDateFormat:@"LLLLL"]; NSLog(@"LLLLL date format: %@",[formatter stringFromDate:date]);
我已经使用en_US,en_GB,es_ES,de_DE,fr_FR和it_IT进行了测试.法语和德语语言环境在日历应用程序中显示完整的月份名称,其余显示短名称.
测试代码看起来很有希望的一件事是,只有法国和德国的地区在shortMonthSymbols的末尾有一段时间.
那么我运行以下代码来查找在短月份符号中使用标点符号的所有区域设置:
NSMutableArray *hasDot = [[NSMutableArray alloc] init]; NSMutableArray *noDot = [[NSMutableArray alloc] init]; NSCharacterSet *letters = [NSCharacterSet letterCharacterSet]; NSArray *locales = [NSLocale availableLocaleIdentifiers]; for (NSString *locid in locales) { NSLocale *locale = [NSLocale localeWithLocaleIdentifier:locid]; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setLocale:locale]; NSArray *shortNames = [formatter shortMonthSymbols]; //NSLog(@"locale: %@,short names: %@",locid,shortNames[10]); NSString *nov = shortNames[10]; unichar char1 = [nov characterAtIndex:0]; unichar charN = [nov characterAtIndex:nov.length - 1]; if ([letters characterIsMember:char1] && [letters characterIsMember:charN]) { [noDot addObject:locid]; } else { [hasDot addObject:locid]; } } NSLog(@"no dot: %@",[noDot sortedArrayUsingSelector:@selector(compare:)]); NSLog(@"has dot: %@",[hasDot sortedArrayUsingSelector:@selector(compare:)]);
通过结果扫描,我发现荷兰语区域在短月份的符号中使用了一段时间.但是,对日历应用程序的快速测试显示,当设备设置为荷兰语(nl_NL)时,日历应用程序会显示较短的月份名称.啊.
更新2:
我已经测试了几个地方.以下显示长月名:
fr_FR,ru_RU,sv_SE(实际上是每种语言的所有语言环境)
以下(和我确定更多)显示短的一个月:
en_US,it_IT,nl_NL,ca_ES,uk_UA,ro_RO(实际上是每种语言的所有语言环境)
解决方法
我们来看看它的反汇编:
EventKitUI`CurrentLocaleRequiresUnabbrevatedMonthNames: 0x102c6bec7: pushq %rbp 0x102c6bec8: movq %rsp,%rbp 0x102c6becb: pushq %r15 0x102c6becd: pushq %r14 0x102c6becf: pushq %rbx 0x102c6bed0: subq $0xb8,%rsp 0x102c6bed7: movq 0x14a3aa(%rip),%r15 ; (void *)0x0000000104e93070: __stack_chk_guard 0x102c6bede: movq (%r15),%rax 0x102c6bee1: movq %rax,-0x20(%rbp) 0x102c6bee5: cmpq $0x0,0x1c01fb(%rip) ; CurrentLocaleRequiresUnabbrevatedMonthNames.usesFullLengthMonthNames + 6 0x102c6beed: je 0x102c6beff ; CurrentLocaleRequiresUnabbrevatedMonthNames + 56 0x102c6beef: movb 0x1c01eb(%rip),%al ; CurrentLocaleRequiresUnabbrevatedMonthNames.hasChecked 0x102c6bef5: xorb $0x1,%al 0x102c6bef7: testb $0x1,%al 0x102c6bef9: je 0x102c6c0d6 ; CurrentLocaleRequiresUnabbrevatedMonthNames + 527 0x102c6beff: movq 0x1b583a(%rip),%rdi ; (void *)0x00000001025dae58: NSLocale 0x102c6bf06: movq 0x1aef23(%rip),%rsi ; "currentLocale" 0x102c6bf0d: movq 0x14a524(%rip),%r14 ; (void *)0x0000000104945000: objc_msgSend 0x102c6bf14: callq *%r14 0x102c6bf17: movq %rax,%rdi 0x102c6bf1a: callq 0x102d29920 ; symbol stub for: objc_retainAutoreleasedReturnValue 0x102c6bf1f: movq %rax,%rbx 0x102c6bf22: movq 0x14a227(%rip),%rax ; (void *)0x00000001025a3cd8: NSLocaleLanguageCode 0x102c6bf29: movq (%rax),%rdx 0x102c6bf2c: movq 0x1ae12d(%rip),%rsi ; "objectForKey:" 0x102c6bf33: movq %rbx,%rdi 0x102c6bf36: callq *%r14 0x102c6bf39: movq %rax,%rdi 0x102c6bf3c: callq 0x102d29920 ; symbol stub for: objc_retainAutoreleasedReturnValue 0x102c6bf41: movq %rax,%r14 0x102c6bf44: movq %rbx,%rdi 0x102c6bf47: callq *0x14a4f3(%rip) ; (void *)0x00000001049429b0: objc_release 0x102c6bf4d: movq 0x1c0194(%rip),%rdi ; __languagesRequiringUnabbreviatedMonthNames 0x102c6bf54: testq %rdi,%rdi 0x102c6bf57: jne 0x102c6c0b0 ; CurrentLocaleRequiresUnabbrevatedMonthNames + 489 0x102c6bf5d: leaq 0x15425c(%rip),%rax ; @"ru" 0x102c6bf64: movq %rax,-0xd0(%rbp) 0x102c6bf6b: leaq 0x1524ce(%rip),%rax ; @"de" 0x102c6bf72: movq %rax,-0xc8(%rbp) 0x102c6bf79: leaq 0x154260(%rip),%rax ; @"fr" 0x102c6bf80: movq %rax,-0xc0(%rbp) 0x102c6bf87: leaq 0x154272(%rip),%rax ; @"fi" 0x102c6bf8e: movq %rax,-0xb8(%rbp) 0x102c6bf95: leaq 0x154284(%rip),%rax ; @"pt" 0x102c6bf9c: movq %rax,-0xb0(%rbp) 0x102c6bfa3: leaq 0x154296(%rip),%rax ; @"no" 0x102c6bfaa: movq %rax,-0xa8(%rbp) 0x102c6bfb1: leaq 0x1542a8(%rip),%rax ; @"nb" 0x102c6bfb8: movq %rax,-0xa0(%rbp) 0x102c6bfbf: leaq 0x1542ba(%rip),%rax ; @"nn" 0x102c6bfc6: movq %rax,-0x98(%rbp) 0x102c6bfcd: leaq 0x1542cc(%rip),%rax ; @"sv" 0x102c6bfd4: movq %rax,-0x90(%rbp) 0x102c6bfdb: leaq 0x1542de(%rip),%rax ; @"he" 0x102c6bfe2: movq %rax,-0x88(%rbp) 0x102c6bfe9: leaq 0x1542f0(%rip),%rax ; @"th" 0x102c6bff0: movq %rax,-0x80(%rbp) 0x102c6bff4: leaq 0x154305(%rip),%rax ; @"hi" 0x102c6bffb: movq %rax,-0x78(%rbp) 0x102c6bfff: leaq 0x15431a(%rip),%rax ; @"bn" 0x102c6c006: movq %rax,-0x70(%rbp) 0x102c6c00a: leaq 0x15432f(%rip),%rax ; @"mr" 0x102c6c011: movq %rax,-0x68(%rbp) 0x102c6c015: leaq 0x154344(%rip),%rax ; @"ur" 0x102c6c01c: movq %rax,-0x60(%rbp) 0x102c6c020: leaq 0x154359(%rip),%rax ; @"te" 0x102c6c027: movq %rax,-0x58(%rbp) 0x102c6c02b: leaq 0x15436e(%rip),%rax ; @"ta" 0x102c6c032: movq %rax,-0x50(%rbp) 0x102c6c036: leaq 0x154383(%rip),%rax ; @"gu" 0x102c6c03d: movq %rax,-0x48(%rbp) 0x102c6c041: leaq 0x154398(%rip),%rax ; @"kn" 0x102c6c048: movq %rax,-0x40(%rbp) 0x102c6c04c: leaq 0x1543ad(%rip),%rax ; @"ml" 0x102c6c053: movq %rax,-0x38(%rbp) 0x102c6c057: leaq 0x1543c2(%rip),%rax ; @"ne" 0x102c6c05e: movq %rax,-0x30(%rbp) 0x102c6c062: leaq 0x1543d7(%rip),%rax ; @"pa" 0x102c6c069: movq %rax,-0x28(%rbp) 0x102c6c06d: movq 0x1b55ec(%rip),%rdi ; (void *)0x00000001025d9cd8: NSArray 0x102c6c074: movq 0x1ae5cd(%rip),%rsi ; "arrayWithObjects:count:" 0x102c6c07b: leaq -0xd0(%rbp),%rdx 0x102c6c082: movl $0x16,%ecx 0x102c6c087: callq *0x14a3ab(%rip) ; (void *)0x0000000104945000: objc_msgSend 0x102c6c08d: movq %rax,%rdi 0x102c6c090: callq 0x102d29920 ; symbol stub for: objc_retainAutoreleasedReturnValue 0x102c6c095: movq 0x1c004c(%rip),%rdi ; __languagesRequiringUnabbreviatedMonthNames 0x102c6c09c: movq %rax,0x1c0045(%rip) ; __languagesRequiringUnabbreviatedMonthNames 0x102c6c0a3: callq *0x14a397(%rip) ; (void *)0x00000001049429b0: objc_release 0x102c6c0a9: movq 0x1c0038(%rip),%rdi ; __languagesRequiringUnabbreviatedMonthNames 0x102c6c0b0: movq 0x1ae6c1(%rip),%rsi ; "containsObject:" 0x102c6c0b7: movq %r14,%rdx 0x102c6c0ba: callq *0x14a378(%rip) ; (void *)0x0000000104945000: objc_msgSend 0x102c6c0c0: movb %al,0x1c001b(%rip) ; CurrentLocaleRequiresUnabbrevatedMonthNames.usesFullLengthMonthNames 0x102c6c0c6: movb $0x1,0x1c0013(%rip) ; __overlayCalendarGeneration + 7 0x102c6c0cd: movq %r14,%rdi 0x102c6c0d0: callq *0x14a36a(%rip) ; (void *)0x00000001049429b0: objc_release 0x102c6c0d6: movb 0x1c0005(%rip),%al ; CurrentLocaleRequiresUnabbrevatedMonthNames.usesFullLengthMonthNames 0x102c6c0dc: movq (%r15),%rcx 0x102c6c0df: cmpq -0x20(%rbp),%rcx 0x102c6c0e3: jne 0x102c6c0f3 ; CurrentLocaleRequiresUnabbrevatedMonthNames + 556 0x102c6c0e5: addq $0xb8,%rsp 0x102c6c0ec: popq %rbx 0x102c6c0ed: popq %r14 0x102c6c0ef: popq %r15 0x102c6c0f1: popq %rbp 0x102c6c0f2: retq 0x102c6c0f3: callq 0x102d29a1c ; symbol stub for: __stack_chk_fail
您可以看到,它创建一个需要未经缩短的月份名称的语言环境数组.然后,它将比较当前区域设置是否是这些区域设置之一.
在代码中硬编码.
对于缩写月份,它使用LLL格式(如EventKitUI`CalStringForMonth所示),对于未缩短的月份,它使用LLLL格式(如EventKitUI`CalLongStringForMonth中所示).
干杯