В отличие от остального мира, использующего день-месяц-год, в США используются форматы месяц-день-год.
Я хотел бы программно определить, использует ли пользователь день-месяц или месяц-день.
Я могу сделать это с помощью следующего, но я не уверен, есть ли более простой способ?
String localisedDateFormat = ((SimpleDateFormat) SimpleDateFormat.getDateInstance()).toPattern().toLowerCase();
boolean usFormat = localisedDateFormat.indexOf('d') > localisedDateFormat.indexOf('m');
Я не думаю, что это возможно с DateTimeFormatter
, так как вы не можете получить базовый pattern
.
Из любопытства, почему вы хотите это сделать? Чтобы создать пользовательский интерфейс с отдельными полями ввода для частей даты?
@JonK именно из-за этого нюанса я хотел получить это на основе локали.
@VGR анализирует данные из файлов. У меня есть предопределенный набор форматов даты, которые использует приложение, но в зависимости от локали они могут быть (например) в формате dd/MM/yy или MM/dd/yy. Я использую локаль для соответствующего изменения форматов.
Есть ли причина не использовать DateFormat.getDateInstance(DateFormat.SHORT, locale)
или DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(locale)
?
@VGR это были репрезентативные примеры. Допустим, это какой-то другой формат, например ddMMyyyy против MMddyyyy — формат данных находится вне моего контроля, но использование Locale может помочь мне создать формат даты.
Я думаю, вы не можете определить локаль (или формат) только по строке. А как насчет 01022019, это 2 января или 1 февраля?
@FrancescoPitzalis нет, но я могу определить локаль данных от пользователя. Я знаю об ограничениях этого.
Выкройку можно получить у DateTimeFormatterBuilder.getLocalizedDateTimePattern
. Настоятельно рекомендуется вместо давно устаревшего SimpleDateFormat
.
@Jakg, если у вас есть языковой стандарт пользователя, и вы можете с уверенностью предположить, что это языковой стандарт его ввода (я бы так и сделал), вы обязательно должны основывать свое решение на нем.
localisedDateFormat.indexOf('m')
не дает вам того, что вы хотите. Буквы шаблона формата чувствительны к регистру! ТАКЖЕ вы должны проверить наличие -1
на тот случай, если буквы там нет.
@ОлеВ.В. Сначала я убрал формат в нижнем регистре. Вы правы на -1.
Извините, пропустил нижний корпус. Я бы не стал этого делать сам, на всякий случай (без каламбура).
Вы не можете разделить локали на «сегменты» MDY
/ DMY
/ YMD
, потому что порядок может зависеть от формата даты (короткий/средний/длинный полный). Например, в en-CA используется «25 июня 2010 г.» (МДГ) для длинного формата и «2010-06-25» (ГМД) для короткого формата.
TL;DR: Вызовите этот вспомогательный метод, который возвращает YMD
, DMY
или MDY
.
public static String getDateFieldOrder(Locale locale) {
SimpleDateFormat fmt = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale));
return fmt.toPattern().replaceAll("[^yMd]|(?<=(.))\\1", "").toUpperCase();
}
Чтобы получить порядок полей, попросите DateFormat
и проанализируйте шаблон, используемый для его построения:
SimpleDateFormat fmt = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale));
String pattern = fmt.toPattern();
Это даст вам такие шаблоны:
dd.MM.yy
M/d/yy
y-MM-dd
d. M. y
Итак, убираем небуквы и повторяющиеся буквы:
pattern = pattern.replaceAll("\\P{L}", "").replaceAll("(.)\\1+", "$1");
Чтобы увидеть потенциальные результаты, вы можете запустить этот код (Java 5+):
Map<String, Set<String>> map = new TreeMap<String, Set<String>>();
for (Locale locale : Locale.getAvailableLocales()) {
SimpleDateFormat fmt = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale));
String pattern = fmt.toPattern().replaceAll("\\P{L}", "").replaceAll("(.)\\1+", "$1");
Set<String> set = map.get(pattern);
if (set == null)
map.put(pattern, set = new TreeSet<String>());
set.add(locale.getDisplayName(Locale.US));
}
for (Entry<String, Set<String>> entry : map.entrySet())
System.out.println(entry.getKey() + " = " + entry.getValue());
Пример вывода (Java 11)
GyMd = [Japanese (Japan, JP, Japanese Calendar)]
Mdy = [Bodo, Bodo (India), Cherokee, Cherokee (United States), English, English (American Samoa), English (Burundi), English (Guam), English (Marshall Islands), English (Northern Mariana Islands), English (Puerto Rico), English (U.S. Outlying Islands), English (U.S. Virgin Islands), English (United States), English (United States, Computer), Ewe, Ewe (Ghana), Ewe (Togo), Filipino, Filipino (Philippines), Kashmiri, Kashmiri (India), Odia, Odia (India), Spanish (Panama), Spanish (Puerto Rico), Zulu, Zulu (South Africa)]
dMy = [Aghem, Aghem (Cameroon), Albanian, Albanian (Albania), Albanian (Kosovo), Albanian (Macedonia), Amharic, Amharic (Ethiopia), Arabic, Arabic (Algeria), Arabic (Bahrain), Arabic (Chad), Arabic (Comoros), Arabic (Djibouti), Arabic (Egypt), Arabic (Eritrea), Arabic (Iraq), Arabic (Israel), Arabic (Jordan), Arabic (Kuwait), Arabic (Lebanon), Arabic (Libya), Arabic (Mauritania), Arabic (Morocco), Arabic (Oman), Arabic (Palestinian Territories), Arabic (Qatar), Arabic (Saudi Arabia), Arabic (Somalia), Arabic (South Sudan), Arabic (Sudan), Arabic (Syria), Arabic (Tunisia), Arabic (United Arab Emirates), Arabic (Western Sahara), Arabic (World), Arabic (Yemen), Armenian, Armenian (Armenia), Assamese, Assamese (India), Asturian, Asturian (Spain), Asu, Asu (Tanzania), Azerbaijani, Azerbaijani (Cyrillic), Azerbaijani (Cyrillic, Azerbaijan), Azerbaijani (Latin), Azerbaijani (Latin, Azerbaijan), Bafia, Bafia (Cameroon), Bambara, Bambara (Mali), Bangla, Bangla (Bangladesh), Bangla (India), Basaa, Basaa (Cameroon), Belarusian, Belarusian (Belarus), Bemba, Bemba (Zambia), Bena, Bena (Tanzania), Bosnian, Bosnian (Cyrillic), Bosnian (Cyrillic, Bosnia & Herzegovina), Bosnian (Latin), Bosnian (Latin, Bosnia & Herzegovina), Breton, Breton (France), Burmese, Burmese (Myanmar (Burma)), Catalan, Catalan (Andorra), Catalan (France), Catalan (Italy), Catalan (Spain), Catalan (Spain, Valencian), Central Atlas Tamazight, Central Atlas Tamazight (Morocco), Chakma, Chakma (Bangladesh), Chakma (India), Chiga, Chiga (Uganda), Chinese (Hong Kong SAR China), Chinese (Simplified, Hong Kong SAR China), Chinese (Simplified, Macau SAR China), Chinese (Simplified, Singapore), Chinese (Singapore), Chinese (Traditional, Hong Kong SAR China), Chinese (Traditional, Macau SAR China), Colognian, Colognian (Germany), Croatian, Croatian (Bosnia & Herzegovina), Croatian (Croatia), Czech, Czech (Czechia), Danish, Danish (Denmark), Danish (Greenland), Duala, Duala (Cameroon), Dutch, Dutch (Aruba), Dutch (Belgium), Dutch (Caribbean Netherlands), Dutch (Curaçao), Dutch (Netherlands), Dutch (Sint Maarten), Dutch (Suriname), Embu, Embu (Kenya), English (Anguilla), English (Antigua & Barbuda), English (Australia), English (Austria), English (Bahamas), English (Barbados), English (Belgium), English (Belize), English (Bermuda), English (Botswana), English (British Indian Ocean Territory), English (British Virgin Islands), English (Cameroon), English (Cayman Islands), English (Christmas Island), English (Cocos (Keeling) Islands), English (Cook Islands), English (Cyprus), English (Denmark), English (Diego Garcia), English (Dominica), English (Eritrea), English (Europe), English (Falkland Islands), English (Fiji), English (Finland), English (Gambia), English (Germany), English (Ghana), English (Gibraltar), English (Grenada), English (Guernsey), English (Guyana), English (Hong Kong SAR China), English (India), English (Ireland), English (Isle of Man), English (Israel), English (Jamaica), English (Jersey), English (Kenya), English (Kiribati), English (Lesotho), English (Liberia), English (Macau SAR China), English (Madagascar), English (Malawi), English (Malaysia), English (Malta), English (Mauritius), English (Micronesia), English (Montserrat), English (Namibia), English (Nauru), English (Netherlands), English (New Zealand), English (Nigeria), English (Niue), English (Norfolk Island), English (Pakistan), English (Palau), English (Papua New Guinea), English (Philippines), English (Pitcairn Islands), English (Rwanda), English (Samoa), English (Seychelles), English (Sierra Leone), English (Singapore), English (Sint Maarten), English (Slovenia), English (Solomon Islands), English (South Sudan), English (St. Helena), English (St. Kitts & Nevis), English (St. Lucia), English (St. Vincent & Grenadines), English (Sudan), English (Swaziland), English (Switzerland), English (Tanzania), English (Tokelau), English (Tonga), English (Trinidad & Tobago), English (Turks & Caicos Islands), English (Tuvalu), English (Uganda), English (United Kingdom), English (Vanuatu), English (World), English (Zambia), English (Zimbabwe), Estonian, Estonian (Estonia), Ewondo, Ewondo (Cameroon), Faroese, Faroese (Denmark), Faroese (Faroe Islands), Finnish, Finnish (Finland), French, French (Algeria), French (Belgium), French (Benin), French (Burkina Faso), French (Burundi), French (Cameroon), French (Central African Republic), French (Chad), French (Comoros), French (Congo - Brazzaville), French (Congo - Kinshasa), French (Côte d’Ivoire), French (Djibouti), French (Equatorial Guinea), French (France), French (French Guiana), French (French Polynesia), French (Gabon), French (Guadeloupe), French (Guinea), French (Haiti), French (Luxembourg), French (Madagascar), French (Mali), French (Martinique), French (Mauritania), French (Mauritius), French (Mayotte), French (Monaco), French (Morocco), French (New Caledonia), French (Niger), French (Rwanda), French (Réunion), French (Senegal), French (Seychelles), French (St. Barthélemy), French (St. Martin), French (St. Pierre & Miquelon), French (Switzerland), French (Syria), French (Togo), French (Tunisia), French (Vanuatu), French (Wallis & Futuna), Friulian, Friulian (Italy), Fulah, Fulah (Cameroon), Fulah (Guinea), Fulah (Mauritania), Fulah (Senegal), Galician, Galician (Spain), Ganda, Ganda (Uganda), Georgian, Georgian (Georgia), German, German (Austria), German (Belgium), German (Germany), German (Italy), German (Liechtenstein), German (Luxembourg), German (Switzerland), Greek, Greek (Cyprus), Greek (Greece), Gujarati, Gujarati (India), Gusii, Gusii (Kenya), Hausa, Hausa (Ghana), Hausa (Niger), Hausa (Nigeria), Hawaiian, Hawaiian (United States), Hebrew, Hebrew (Israel), Hindi, Hindi (India), Icelandic, Icelandic (Iceland), Igbo, Igbo (Nigeria), Inari Sami, Inari Sami (Finland), Indonesian, Indonesian (Indonesia), Irish, Irish (Ireland), Italian, Italian (Italy), Italian (San Marino), Italian (Switzerland), Italian (Vatican City), Jola-Fonyi, Jola-Fonyi (Senegal), Kabuverdianu, Kabuverdianu (Cape Verde), Kabyle, Kabyle (Algeria), Kako, Kako (Cameroon), Kalenjin, Kalenjin (Kenya), Kamba, Kamba (Kenya), Kannada, Kannada (India), Kazakh, Kazakh (Kazakhstan), Khmer, Khmer (Cambodia), Kikuyu, Kikuyu (Kenya), Konkani, Konkani (India), Koyra Chiini, Koyra Chiini (Mali), Koyraboro Senni, Koyraboro Senni (Mali), Kwasio, Kwasio (Cameroon), Kyrgyz, Kyrgyz (Kyrgyzstan), Langi, Langi (Tanzania), Lao, Lao (Laos), Latvian, Latvian (Latvia), Lingala, Lingala (Angola), Lingala (Central African Republic), Lingala (Congo - Brazzaville), Lingala (Congo - Kinshasa), Lower Sorbian, Lower Sorbian (Germany), Luba-Katanga, Luba-Katanga (Congo - Kinshasa), Luo, Luo (Kenya), Luxembourgish, Luxembourgish (Luxembourg), Luyia, Luyia (Kenya), Macedonian, Macedonian (Macedonia), Machame, Machame (Tanzania), Makhuwa-Meetto, Makhuwa-Meetto (Mozambique), Makonde, Makonde (Tanzania), Malay, Malay (Brunei), Malay (Malaysia), Malay (Singapore), Malayalam, Malayalam (India), Maltese, Maltese (Malta), Marathi, Marathi (India), Masai, Masai (Kenya), Masai (Tanzania), Meru, Meru (Kenya), Morisyen, Morisyen (Mauritius), Mundang, Mundang (Cameroon), Nama, Nama (Namibia), Ngiemboon, Ngiemboon (Cameroon), North Ndebele, North Ndebele (Zimbabwe), Northern Sami (Finland), Norwegian, Norwegian (Norway), Norwegian (Norway, Nynorsk), Norwegian Bokmål, Norwegian Bokmål (Norway), Norwegian Bokmål (Svalbard & Jan Mayen), Norwegian Nynorsk, Norwegian Nynorsk (Norway), Nuer, Nuer (South Sudan), Nyankole, Nyankole (Uganda), Oromo, Oromo (Ethiopia), Oromo (Kenya), Ossetic, Ossetic (Georgia), Ossetic (Russia), Polish, Polish (Poland), Portuguese, Portuguese (Angola), Portuguese (Brazil), Portuguese (Cape Verde), Portuguese (Equatorial Guinea), Portuguese (Guinea-Bissau), Portuguese (Luxembourg), Portuguese (Macau SAR China), Portuguese (Mozambique), Portuguese (Portugal), Portuguese (Switzerland), Portuguese (São Tomé & Príncipe), Portuguese (Timor-Leste), Punjabi, Punjabi (Arabic), Punjabi (Arabic, Pakistan), Punjabi (Gurmukhi), Punjabi (Gurmukhi, India), Quechua, Quechua (Bolivia), Quechua (Ecuador), Quechua (Peru), Romanian, Romanian (Moldova), Romanian (Romania), Romansh, Romansh (Switzerland), Rombo, Rombo (Tanzania), Rundi, Rundi (Burundi), Russian, Russian (Belarus), Russian (Kazakhstan), Russian (Kyrgyzstan), Russian (Moldova), Russian (Russia), Russian (Ukraine), Rwa, Rwa (Tanzania), Samburu, Samburu (Kenya), Sango, Sango (Central African Republic), Sangu, Sangu (Tanzania), Scottish Gaelic, Scottish Gaelic (United Kingdom), Sena, Sena (Mozambique), Serbian, Serbian (Bosnia & Herzegovina), Serbian (Cyrillic), Serbian (Cyrillic, Bosnia & Herzegovina), Serbian (Cyrillic, Kosovo), Serbian (Cyrillic, Montenegro), Serbian (Cyrillic, Serbia), Serbian (Latin), Serbian (Latin, Bosnia & Herzegovina), Serbian (Latin, Kosovo), Serbian (Latin, Montenegro), Serbian (Latin, Serbia), Serbian (Montenegro), Serbian (Serbia and Montenegro), Serbian (Serbia), Shambala, Shambala (Tanzania), Slovak, Slovak (Slovakia), Slovenian, Slovenian (Slovenia), Soga, Soga (Uganda), Somali, Somali (Djibouti), Somali (Ethiopia), Somali (Kenya), Somali (Somalia), Spanish, Spanish (Argentina), Spanish (Belize), Spanish (Bolivia), Spanish (Brazil), Spanish (Canary Islands), Spanish (Ceuta & Melilla), Spanish (Chile), Spanish (Colombia), Spanish (Costa Rica), Spanish (Cuba), Spanish (Dominican Republic), Spanish (Ecuador), Spanish (El Salvador), Spanish (Equatorial Guinea), Spanish (Guatemala), Spanish (Honduras), Spanish (Latin America), Spanish (Mexico), Spanish (Nicaragua), Spanish (Paraguay), Spanish (Peru), Spanish (Philippines), Spanish (Spain), Spanish (United States), Spanish (Uruguay), Spanish (Venezuela), Standard Moroccan Tamazight, Standard Moroccan Tamazight (Morocco), Swahili, Swahili (Congo - Kinshasa), Swahili (Kenya), Swahili (Tanzania), Swahili (Uganda), Swedish (Finland), Swiss German, Swiss German (France), Swiss German (Liechtenstein), Swiss German (Switzerland), Tachelhit, Tachelhit (Latin), Tachelhit (Latin, Morocco), Tachelhit (Tifinagh), Tachelhit (Tifinagh, Morocco), Taita, Taita (Kenya), Tajik, Tajik (Tajikistan), Tamil, Tamil (India), Tamil (Malaysia), Tamil (Singapore), Tamil (Sri Lanka), Tasawaq, Tasawaq (Niger), Tatar, Tatar (Russia), Telugu, Telugu (India), Teso, Teso (Kenya), Teso (Uganda), Thai, Thai (Thailand), Thai (Thailand, TH, Thai Digits), Tigrinya, Tigrinya (Eritrea), Tigrinya (Ethiopia), Tongan, Tongan (Tonga), Turkish, Turkish (Cyprus), Turkish (Turkey), Turkmen, Turkmen (Turkmenistan), Ukrainian, Ukrainian (Ukraine), Upper Sorbian, Upper Sorbian (Germany), Urdu, Urdu (India), Urdu (Pakistan), Uzbek, Uzbek (Cyrillic), Uzbek (Cyrillic, Uzbekistan), Uzbek (Latin), Uzbek (Latin, Uzbekistan), Vai, Vai (Latin), Vai (Latin, Liberia), Vai (Vai), Vai (Vai, Liberia), Vietnamese, Vietnamese (Vietnam), Vunjo, Vunjo (Tanzania), Welsh, Welsh (United Kingdom), Western Frisian, Western Frisian (Netherlands), Wolof, Wolof (Senegal), Yangben, Yangben (Cameroon), Yiddish, Yiddish (World), Yoruba, Yoruba (Benin), Yoruba (Nigeria), Zarma, Zarma (Niger)]
dMyг = [Bulgarian, Bulgarian (Bulgaria)]
yMd = [, Afrikaans, Afrikaans (Namibia), Afrikaans (South Africa), Akan, Akan (Ghana), Basque, Basque (Spain), Cantonese, Cantonese (Simplified), Cantonese (Simplified, China), Cantonese (Traditional), Cantonese (Traditional, Hong Kong SAR China), Central Kurdish, Central Kurdish (Iran), Central Kurdish (Iraq), Chechen, Chechen (Russia), Chinese, Chinese (China), Chinese (Simplified), Chinese (Simplified, China), Chinese (Taiwan), Chinese (Traditional), Chinese (Traditional, Taiwan), Church Slavic, Church Slavic (Russia), Cornish, Cornish (United Kingdom), Dzongkha, Dzongkha (Bhutan), English (Canada), English (South Africa), English (Sweden), Esperanto, Esperanto (World), French (Canada), Hungarian, Hungarian (Hungary), Japanese, Japanese (Japan), Kalaallisut, Kalaallisut (Greenland), Kinyarwanda, Kinyarwanda (Rwanda), Korean, Korean (North Korea), Korean (South Korea), Lakota, Lakota (United States), Lithuanian, Lithuanian (Lithuania), Low German, Low German (Germany), Low German (Netherlands), Malagasy, Malagasy (Madagascar), Manx, Manx (Isle of Man), Mazanderani, Mazanderani (Iran), Metaʼ, Metaʼ (Cameroon), Mongolian, Mongolian (Mongolia), Nepali, Nepali (India), Nepali (Nepal), Ngomba, Ngomba (Cameroon), Northern Luri, Northern Luri (Iran), Northern Luri (Iraq), Northern Sami, Northern Sami (Norway), Northern Sami (Sweden), Pashto, Pashto (Afghanistan), Persian, Persian (Afghanistan), Persian (Iran), Prussian, Prussian (World), Sakha, Sakha (Russia), Shona, Shona (Zimbabwe), Sichuan Yi, Sichuan Yi (China), Sindhi, Sindhi (Pakistan), Sinhala, Sinhala (Sri Lanka), Swedish, Swedish (Sweden), Swedish (Åland Islands), Tibetan, Tibetan (China), Tibetan (India), Uyghur, Uyghur (China), Uzbek (Arabic), Uzbek (Arabic, Afghanistan), Volapük, Volapük (World), Walser, Walser (Switzerland)]
При необходимости вы также можете удалить шаблонные буквы G
и r
. Вместо replaceAll("\\P{L}", "")
используйте replaceAll("[^yMd]", "")
.
Конечно, вы можете вызвать toUpperCase()
, если предпочитаете такие значения, как YMD
, DMY
и MDY
.
Красиво продумано. Зачем показывать молодым использование давно устаревшего класса SimpleDateFormat
, когда DateTimeFormatterBuilder.getLocalizedDateTimePattern
может дать вам то же самое?
@ОлеВ.В. По той же причине я изменил тестовый код с использования потоков на старомодный: чтобы дать решение, которое может использовать любой, даже программисты Android и другие бедняки, застрявшие на Java 7 или более ранней версии. Не похоже, что SimpleDateFormat
уходит (еще даже не объявлено устаревшим), и для это проблемы со старым API не проблема.
Спасибо! Использовал модифицированную версию с использованием метода DateTimeFormatterBuilder.getLocalizedDateTimePattern
, обсуждавшегося в комментариях. Мне гораздо больше нравится идея возвращать дескриптор, а не простое логическое значение, особенно теперь, когда я знаю, что есть третий случай, который я не учел (yMd
).
Для всех, кому любопытно (как и мне), r
в болгарских форматах — это литерал (а не шаблонная буква). Строка формата — d.MM.yy 'г'.
, поэтому дата имеет формат 26.07.19 г.
. Я не знаю, что это значит.
@ОлеВ.В. Согласно эта страница, это начальная буква слова година / год.
MDY
формат не является исключительно американским - несколько других стран также используют его, хотя является встречается гораздо реже, чем форматDMY