2014-11-13 2 views
13

В приложении iOS 7 или 8 приложение Calendar Calendar делает то, что я не смог выяснить.Знайте, когда следует использовать короткие или полные имена месяцев

В некоторых местах, например en_US, приложение «Календарь» показывает короткие (3-буквенные) месячные имена.

В других местах, например de_DE, приложение «Календарь» показывает полные месячные имена. Интересно, что в локали en_DE показаны короткие месячные имена, поэтому, похоже, он привязан к языку больше, чем формат региона.

Что я не могу понять, так это узнать, какой формат месяца использовать.

Независимо от того, что касается моего устройства, NSDateFormatter standaloneShortMonthSymbols дает мне названия на 3 письма и NSDateFormatter standaloneMonthSymbols дает мне полные месячные имена.

Есть также пробовал:

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

и возвращает ту же LLL для обоих en_US и de_DE.

Глядя на NSLocale, по-видимому, не существует значения, определяющего, использовать ли короткие или полные месячные имена.

В NSCalendar, NSDateFormatter, или NSLocale не найдено ничего, чтобы определить, какой формат месяца использовать.

Кто-нибудь знает, как это сделать?

Update:

Я думал, что я нашел решение, но это не работает для всех языков, которые я пробовал. Я побежал следующий код с различными местами, чтобы увидеть, если я мог бы найти что-то общее между локалями, которые показывают короткие и длинные месяцы имен в приложении Календаря:

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). Тьфу.

Update 2:

Я проверил еще несколько локалей.Следующие шоу длинные имена месяц:

fr_FR, de_DE, ru_RU, sv_SE (на самом деле все локали для каждого из этих языков)

следующее (и я уверен, что многие другие) показывают короткий месяц:

en_US, eN_GB, es_ES, it_IT, nl_NL, ca_ES, uk_UA, ro_RO (фактически все языки для каждого из этих языков)

+0

Я предполагаю, что я всегда полагал, что NSDateFormatterStyle под контролем, что, если вы не дали полный формат даты. Я бы предположил, что NSDateFormatterMediumStyle даст короткие имена месяцев. –

+0

Различные 'NSDateFormatterXXXStyle' предназначены для форматирования полной даты (день, месяц и год). Мне просто нужны месячные имена, как показано в приложении «Календарь». – rmaddy

+0

Итак, вы хотите, чтобы название месяца, в стандартном формате локали, не имело ничего другого? «Мар» для en_US и «Marts» для de_DE? –

ответ

17

После того, как каждый так часто, приходит вопрос стоит посмотреть в. Рик, для вас я отлаживал приложение «Календарь» (может быть сделано с помощью процесса MobileCal). Все сводится к EventKitUI`CurrentLocaleRequiresUnabbrevatedMonthNames, который отвечает на нужный вопрос.

Давайте посмотрим на его разборке:

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).

Приветствия

+0

Я боялся, что это просто жесткий список в приложении Calendar. Где вы нашли этот метод «CurrentLocaleRequiresUnabbrevatedMonthNames»? – rmaddy

+0

Это на самом деле в 'EventKitUI', поэтому вы можете теоретически использовать его и использовать. Я напечатал иерархию представления месяца в окне MobileCal и заметил, что месяцы - это метки. Поэтому поставим точку останова на '[UILabel setText:]', которая была обнаружена в '_reloadMonthNameLabel', который является внутренним методом« MobileCal », но тот вызывает функции из« EventKitUI ». –

+0

Я думаю, вы могли бы скрыть свое использование функции с помощью 'dlsym' и сделать некоторые манипуляции с строкой C, чтобы скрыть' CurrentLocaleRequiresUnabbrevatedMonthNames'. –

Смежные вопросы