Подтвердить что ты не робот

Знайте, когда следует использовать короткие или полные имена месяцев

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

Обновление 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 (фактически все локали для каждого из этих языков)

4b9b3361

Ответ 1

Как-то раз так часто возникает вопрос, на который стоит обратить внимание. Рик, для вас я отлаживал приложение "Календарь" (может быть сделано с помощью процесса 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).

Приветствия