2014-11-13 12 views
13

Unter iOS 7 oder 8, die Stock Calendar App tut etwas, was ich nicht herausfinden konnte.Wissen, wann Kurz- oder Vollmonatsnamen zu verwenden sind

Unter einigen Gebietsschemas wie zeigt die Kalender-App die kurzen (3-Buchstaben) Monatsnamen an.

Unter anderen Gebietsschemas wie de_DE zeigt die Kalender-App die vollständigen Monatsnamen. Interessanterweise zeigt das Gebietsschema en_DE die Namen der kurzen Monate an, so dass es anscheinend mehr an die Sprache gebunden ist als das Region-Format.

Was ich nicht herausfinden kann, ist, wie man das zu verwendende Monatsformat erkennt.

Unabhängig von der Ländereinstellung meines Geräts, NSDateFormatter standaloneShortMonthSymbols gibt mir die 3-Buchstaben-Monatsnamen und NSDateFormatter standaloneMonthSymbols gibt mir die vollständigen Monatsnamen.

Ist auch versucht:

NSString *monthformat = [NSDateFormatter dateFormatFromTemplate:@"LLL" options:0 locale:[NSLocale currentLocale]]; 

und das gibt die gleiche LLL sowohl für en_US und de_DE zurück.

Mit Blick auf NSLocale scheint es keinen Wert zu geben, der bestimmt, ob kurze oder vollständige Monatsnamen verwendet werden sollen.

In NSCalendar, NSDateFormatter oder NSLocale scheint nichts zu sein, um festzustellen, welches Monatsformat verwendet werden soll.

Hat jemand eine Idee, wie man diese Bestimmung macht?

Update:

Ich dachte, ich eine Lösung gefunden, aber es funktioniert nicht für alle Gegenden, die ich versucht. Ich lief den folgenden Code mit verschiedenen Schauplätzen, um zu sehen, ob ich etwas gemeinsam zwischen Lokalisierungen, die den kurzen und langen Monate Namen in dem Kalender-App zeigen, finden kann:

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]); 

ich mit en_US, getestet hatte en_GB, es_ES, de_DE , fr_FR und it_IT. Die französischen und deutschen Gebietsschemas zeigen den vollständigen Monatsnamen in der Kalender-App an, während der Rest den Kurznamen anzeigt.

Die eine Sache, die vielversprechend mit dem Test-Code sah, ist, dass nur die Französisch und Deutsch Gebietsschemas eine Periode am Ende der shortMonthSymbols haben.

Also lief ich den folgenden Code alle Gegenden zu finden, die Zeichensetzung in den kurzen Monat Symbole und solche verwenden, die dies nicht tun:

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:)]); 

Scanning durch die Ergebnisse sah ich, dass die niederländischen Gegenden einen Zeitraum verwendet in den kurzen Monatszeichen. Ein kurzer Test der Kalender-App ergab jedoch, dass die Kalender-App kurze Monatsnamen enthielt, als das Gerät auf Niederländisch eingestellt war (nl_NL). Pfui.

Update 2:

ich ein paar mehr locales getestet haben.Die folgenden zeigen lange Monatsnamen:

fr_FR, de_DE, ru_RU, sv_SE (eigentlich alle Schauplätze für jede dieser Sprachen)

die folgenden (und ich bin sicher, dass viele mehr) zeigen die Kurz Monat:

en_US, de_DE, es_ES, it_IT, nl_NL, ca_ES, uk_UA, ro_RO (eigentlich alle Schauplätze für jede dieser Sprachen)

+0

Ich glaube, ich dachte immer, dass NSDateFormatterStyle gesteuert, dass, wenn Sie nicht ein volles Datumsformat geben hat. Ich würde vermuten, dass NSDateFormatterMediumStyle die kurzen Monatsnamen geben würde. –

+0

Die verschiedenen 'NSDateFormatterXXXStyle' dienen zum Formatieren eines vollständigen Datums (Tag, Monat und Jahr). Ich brauche nur die Monatsnamen wie in der Kalender App. – rmaddy

+0

Sie möchten also den Monatsnamen im Standardgebietsschema-Format ohne etwas anderes? "Mar" für en_US und "Marts" für de_DE? –

Antwort

17

Einmal in jeder so oft, es kommt eine Frage wert suchen. Rick, für dich habe ich die Kalender-App debugged (kann durch Anfügen an den MobileCal-Prozess erfolgen). Es kommt alles auf EventKitUI`CurrentLocaleRequiresUnabbrevatedMonthNames, die die gewünschte Frage beantwortet.

Schauen wir uns seine Demontage:

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 

Wie Sie sehen können, erstellt es eine Reihe von Lokalisierungen, die nicht abgekürzten Monatsnamen benötigen. Es vergleicht dann, ob das aktuelle Gebietsschema eines dieser Gebietsschemas ist.

Im Code fest codiert.

Für abgekürzte Monate, es verwendet das LLL-Format (wie in EventKitUI`CalStringForMonth gesehen), und für ungekürzte Monate, es verwendet das LLLL-Format (wie in EventKitUI`CalLongStringForMonth gesehen).

Prost

+0

Ich hatte Angst, dass es nur eine fest codierte Liste in der Kalender App ist. Wo haben Sie diese 'CurrentLocaleRequiresUnabbrevatedMonthNames' Methode gefunden? – rmaddy

+0

Es ist tatsächlich in 'EventKitUI', also können Sie es theoretisch" extern "und verwenden Sie es. Ich habe die Hierarchie der Monatsansicht im MobileCal-Fenster gedruckt und festgestellt, dass die Monate Etiketten sind. Setzen Sie also einen Breakpoint auf '[UILabel setText:]', das in '_reloadMonthNameLabel' gefangen war, was eine interne' MobileCal'-Methode ist, die aber Funktionen von 'EventKitUI' aufruft. –

+0

Ich denke, Sie könnten Ihre Verwendung der Funktion mit 'dlsym' verstecken und eine C-String-Manipulation machen, um' CurrentLocaleRequiresUnabbrevatedMonthNames' zu verstecken. –