get calendar pattern for a given locale [duplicate] - java

It is quite easy to format and parse Java Date (or Calendar) classes using instances of DateFormat.
I could format the current date into a short localized date like this:
DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
String today = formatter.format(new Date());
My problem is that I need to obtain this localized pattern string (something like "MM/dd/yy").
This should be a trivial task, but I just couldn't find the provider.

For SimpleDateFormat, You call toLocalizedPattern()
EDIT:
For Java 8 users:
The Java 8 Date Time API is similar to Joda-time. To gain a localized pattern we can use class
DateTimeFormatter
DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
Note that when you call toString() on LocalDate, you will get date in format ISO-8601
Note that Date Time API in Java 8 is inspired by Joda Time and most solution can be based on questions related to time.

For those still using Java 7 and older:
You can use something like this:
DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
String pattern = ((SimpleDateFormat)formatter).toPattern();
String localPattern = ((SimpleDateFormat)formatter).toLocalizedPattern();
Since the DateFormat returned From getDateInstance() is instance of SimpleDateFormat.
Those two methods should really be in the DateFormat too for this to be less hacky, but they currently are not.

It may be strange, that I am answering my own question, but I believe, I can add something to the picture.
ICU implementation
Obviously, Java 8 gives you a lot, but there is also something else: ICU4J. This is actually the source of Java original implementation of things like Calendar, DateFormat and SimpleDateFormat, to name a few.
Therefore, it should not be a surprise that ICU's SimpleDateFormat also contains methods like toPattern() or toLocalizedPattern(). You can see them in action here:
DateFormat fmt = DateFormat.getPatternInstance(
DateFormat.YEAR_MONTH,
Locale.forLanguageTag("pl-PL"));
if (fmt instanceof SimpleDateFormat) {
SimpleDateFormat sfmt = (SimpleDateFormat) fmt;
String pattern = sfmt.toPattern();
String localizedPattern = sfmt.toLocalizedPattern();
System.out.println(pattern);
System.out.println(localizedPattern);
}
ICU enhancements
This is nothing new, but what I really wanted to point out is this:
DateFormat.getPatternInstance(String pattern, Locale locale);
This is a method that can return a whole bunch of locale specific patterns, such as:
ABBR_QUARTER
QUARTER
YEAR
YEAR_ABBR_QUARTER
YEAR_QUARTER
YEAR_ABBR_MONTH
YEAR_MONTH
YEAR_NUM_MONTH
YEAR_ABBR_MONTH_DAY
YEAR_NUM_MONTH_DAY
YEAR_MONTH_DAY
YEAR_ABBR_MONTH_WEEKDAY_DAY
YEAR_MONTH_WEEKDAY_DAY
YEAR_NUM_MONTH_WEEKDAY_DAY
ABBR_MONTH
MONTH
NUM_MONTH
ABBR_STANDALONE_MONTH
STANDALONE_MONTH
ABBR_MONTH_DAY
MONTH_DAY
NUM_MONTH_DAY
ABBR_MONTH_WEEKDAY_DAY
MONTH_WEEKDAY_DAY
NUM_MONTH_WEEKDAY_DAY
DAY
ABBR_WEEKDAY
WEEKDAY
HOUR
HOUR24
HOUR_MINUTE
HOUR_MINUTE_SECOND
HOUR24_MINUTE
HOUR24_MINUTE_SECOND
HOUR_TZ
HOUR_GENERIC_TZ
HOUR_MINUTE_TZ
HOUR_MINUTE_GENERIC_TZ
MINUTE
MINUTE_SECOND
SECOND
ABBR_UTC_TZ
ABBR_SPECIFIC_TZ
SPECIFIC_TZ
ABBR_GENERIC_TZ
GENERIC_TZ
LOCATION_TZ
Sure, there are quite a few. What is good about them, is that these patterns are actually strings (as in java.lang.String), that is if you use English pattern "MM/d", you'll get locale-specific pattern in return. It might be useful in some corner cases. Usually you would just use DateFormat instance, and won't care about the pattern itself.
Locale-specific pattern vs. localized pattern
The question intention was to get localized, and not the locale-specific pattern. What's the difference?
In theory, toPattern() will give you locale-specific pattern (depending on Locale you used to instantiate (Simple)DateFormat). That is, no matter what target language/country you put, you'll get the pattern composed of symbols like y, M, d, h, H, M, etc.
On the other hand, toLocalizedPattern() should return localized pattern, that is something that is suitable for end users to read and understand. For instance, German middle (default) date pattern would be:
toPattern(): dd.MM.yyyy
toLocalizedPattern(): tt.MM.jjjj (day = Tag, month = Monat, year = Jahr)
The intention of the question was: "how to find the localized pattern that could serve as hint as to what the date/time format is". That is, say we have a date field that user can fill-out using the locale-specific pattern, but I want to display a format hint in the localized form.
Sadly, so far there is no good solution. The ICU I mentioned earlier in this post, partially works. That's because, the data that ICU uses come from CLDR, which is unfortunately partially translated/partially correct. In case of my mother's tongue, at the time of writing, neither patterns, nor their localized forms are correctly translated. And every time I correct them, I got outvoted by other people, who do not necessary live in Poland, nor speak Polish language...
The moral of this story: do not fully rely on CLDR. You still need to have local auditors/linguistic reviewers.

You can use DateTimeFormatterBuilder in Java 8. Following example returns localized date only pattern e.g. "d.M.yyyy".
String datePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
FormatStyle.SHORT, null, IsoChronology.INSTANCE,
Locale.GERMANY); // or whatever Locale

The following code will give you the pattern for the locale:
final String pattern1 = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale)).toPattern();
System.out.println(pattern1);

Java 8 provides some useful features out of the box for working with and formatting/parsing date and time, including handling locales. Here is a brief introduction.
Basic Patterns
In the simplest case to format/parse a date you would use the following code with a String pattern:
DateTimeFormatter.ofPattern("MM/dd/yyyy")
The standard is then to use this with the date object directly for formatting:
return LocalDate.now().format(DateTimeFormatter.ofPattern("MM/dd/yyyy"));
And then using the factory pattern to parse a date:
return LocalDate.parse(dateString, DateTimeFormatter.ofPattern("MM/dd/yyyy"));
The pattern itself has a large number of options that will cover the majority of usecases, a full rundown can be found at the javadoc location here.
Locales
Inclusion of a Locale is fairly simple, for the default locale you have the following options that can then be applied to the format/parse options demonstrated above:
DateTimeFormatter.ofLocalizedDate(dateStyle);
The 'dateStyle' above is a FormatStyle option Enum to represent the full, long, medium and short versions of the localized Date when working with the DateTimeFormatter. Using FormatStyle you also have the following options:
DateTimeFormatter.ofLocalizedTime(timeStyle);
DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle, timeStyle);
The last option allows you to specify a different FormatStyle for the date and the time. If you are not working with the default Locale the return of each of the Localized methods can be adjusted using the .withLocale option e.g
DateTimeFormatter.ofLocalizedTime(timeStyle).withLocale(Locale.ENGLISH);
Alternatively the ofPattern has an overloaded version to specify the locale too
DateTimeFormatter.ofPattern("MM/dd/yyyy",Locale.ENGLISH);
I Need More!
DateTimeFormatter will meet the majority of use cases, however it is built on the DateTimeFormatterBuilder which provides a massive range of options to the user of the builder. Use DateTimeFormatter to start with and if you need these extensive formatting features fall back to the builder.

Please find in the below code which accepts the locale instance and returns the locale specific data format/pattern.
public static String getLocaleDatePattern(Locale locale) {
// Validating if Locale instance is null
if (locale == null || locale.getLanguage() == null) {
return "MM/dd/yyyy";
}
// Fetching the locale specific date pattern
String localeDatePattern = ((SimpleDateFormat) DateFormat.getDateInstance(
DateFormat.SHORT, locale)).toPattern();
// Validating if locale type is having language code for Chinese and country
// code for (Hong Kong) with Date Format as - yy'?'M'?'d'?'
if (locale.toString().equalsIgnoreCase("zh_hk")) {
// Expected application Date Format for Chinese (Hong Kong) locale type
return "yyyy'MM'dd";
}
// Replacing all d|m|y OR Gy with dd|MM|yyyy as per the locale date pattern
localeDatePattern = localeDatePattern.replaceAll("d{1,2}", "dd").replaceAll(
"M{1,2}", "MM").replaceAll("y{1,4}|Gy", "yyyy");
// Replacing all blank spaces in the locale date pattern
localeDatePattern = localeDatePattern.replace(" ", "");
// Validating the date pattern length to remove any extract characters
if (localeDatePattern.length() > 10) {
// Keeping the standard length as expected by the application
localeDatePattern = localeDatePattern.substring(0, 10);
}
return localeDatePattern;
}

Since it's just the locale information you're after, I think what you'll have to do is locate the file which the JVM (OpenJDK or Harmony) actually uses as input to the whole Locale thing and figure out how to parse it. Or just use another source on the web (surely there's a list somewhere). That'll save those poor translators.

You can try something like :
LocalDate fromCustomPattern = LocalDate.parse("20.01.2014", DateTimeFormatter.ofPattern("MM/dd/yy"))

Im not sure about what you want, but...
SimpleDateFormat example:
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yy");
Date date = sdf.parse("12/31/10");
String str = sdf.format(new Date());

Related

How to convert date from English to Arabic

I have this code
frame.sigdate.setText(new SimpleDateFormat("yyyy/M/d").format(new Date()));
which reads the date from my PC with English numbers. What I want to do is convert the date to Arabic numbers.
Is there anything like Local.ar ?
I appreciate any help.
java.time
Locale arabicLocale = Locale.forLanguageTag("ar");
DateTimeFormatter arabicDateFormatter
= DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
.withLocale(arabicLocale)
.withDecimalStyle(DecimalStyle.of(arabicLocale));
LocalDate today = LocalDate.now(ZoneId.of("Asia/Muscat"));
System.out.println(today.format(arabicDateFormatter));
Output:
١٥‏/٤‏/٢٠١٨
The key is withDecimalStyle. Without this call, the formatter would still use western numerals, as in 15‏/4‏/2018. You may want to use a more specific language tag than just ar for Arabic, for example ar-BH for Bahrain or ar-YE for Yemen. See the link at the bottom for possibilities. You should also insert your desired time zone where I put Asia/Muscat.
EDIT: The above has been tested in Java 9. Surprisingly in Java 8 it still uses western (unlocalized) digits. A possible fix (or workaround if you like) is to specify the zero digit explicitly — it will pick up the other digits from it.
DecimalStyle arabicDecimalStyle
= DecimalStyle.of(arabicLocale).withZeroDigit('٠');
DateTimeFormatter arabicDateFormatter
= DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
.withLocale(arabicLocale)
.withDecimalStyle(arabicDecimalStyle);
It’s an Arabic zero between the two apostrophes in the argument to withZeroDigit. Now I get this output on Java 8:
١٥/٠٤/١٨
It’s usually a good idea to use the built-in locale specific formats as I do with ofLocalizedDate in both snippets above. If you need finer control over the format, use ofPattern instead. For example, to get yyyy/mm/dd format:
DateTimeFormatter arabicDateFormatter
= DateTimeFormatter.ofPattern("uuuu/MM/dd", arabicLocale)
.withDecimalStyle(arabicDecimalStyle);
Output:
٢٠١٨/٠٤/١٥
The reason why the format changed from Java 8 to Java 9 is that Java has changed the defaults for where the locale data come from, including the built-in localized date and time formats. You can get the Java 9 format already in Java 8 by setting a system property, for example like this:
System.setProperty("java.locale.providers", "CLDR,JRE,SPI");
With this change the first code snippet above gives the same output on Java 8 as on Java 9:
١٥‏/٤‏/٢٠١٨
The important detail here is that CLDR goes first in the property string. And the advantages are you don’t need to specify your own format pattern string, localization to other locales is straightforward and users won’t be surprised by a change in behaviour once you switch to Java 9 or later.
I am using and recommending java.time, the modern Java date and time API. The SimpleDateFormat class that you used in the question is not only long outdated, it is also notoriously troublesome. IMHO you should avoid it completely. The modern API is so much nicer to work with.
Links
Oracle tutorial: Date Time explaining how to use java.time.
List of supported locales in Java 8
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/MM/yyyy");
String date = "16/08/2011";
Locale arabicLocale = Locale.forLanguageTag("ar-SA");
DateTimeFormatter arabicDateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(arabicLocale).withDecimalStyle(DecimalStyle.of(arabicLocale));
LocalDate today = LocalDate.now(ZoneId.of("Asia/Muscat"));
today = LocalDate.parse(date, formatter);
String dat = today.format(arabicDateFormatter);
System.out.println(dat);
out put ١٦‏/٨‏/٢٠١١
try below approch
java.util.Locale locale = new java.util.Locale("ar");
java.text.DecimalFormat df = (java.text.DecimalFormat)
java.text.DecimalFormat.getNumberInstance(locale);
DateTime dateTimeObjectInUTC = new DateTime(DateTimeZone.UTC);
DateTimeZone dateTimeZoneObject = DateTimeZone.forID("Asia/Riyadh");
java.util.Locale locale = new Locale("ar","SA");
DateTimeFormatter formatter = DateTimeFormat.forStyle("FF").withLocale(locale).withZone(dateTimeZoneObject);
String output = formatter.print(dateTimeObjectInUTC);
This should help!
I am using Joda-Time. Please refer to the Jodatime documentation. DateTimeZone documentation, for example.

Format String into Date considering localization in GWT

I have the problem that I cannot format a String, having in form of "270317" (German version), into a Date.
For accomplishing this, I use GWT.
What I have so far is this:
String input = "270317";
LocaleInfo locale = null;
if (locale == null) {
locale = LocaleInfo.getCurrentLocale();
}
date = DateTimeFormat.getFormat(input).parse(input);
The outcome is always the current date: 07/28/2017
What I want to achieve is to have the date as it is written in the country where the program is being executed.
If that is not really possible then I would prefer to have it written in this way: 03/27/2017.
To parse the input 270317 to a Date, you must provide the expected format (you're using input as the format, which is wrong):
String input = "270317";
Date date = DateTimeFormat.getFormat("ddMMyy").parse(input);
This will parse the date correctly, if the input format is always as day-month-year. If the inputs are produced in a localized format, then you can use DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT) or any other format - but this is locale-specific and it can vary a lot between different environments.
Check your inputs to know if you'll need to use a fixed or a localized format.
After you parsed the date, you can then format it to whatever format you want. If you want a locale-specific format, just use:
DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT).format(date);
This is locale specific, so the output can vary. In my system, I've got:
2017-03-27
Java new Date/Time API
Although you're using GWT, this specific code for date parsing/formatting could be handled by a better API. GWT uses java.util.Date, which has lots of problems and design issues.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
To parse and format a date, you can use a DateTimeFormatter. As you're using only day, month and year, I'm using the LocalDate class (which has only the date fields):
String input = "270317";
// parse the date
DateTimeFormatter parser = DateTimeFormatter.ofPattern("ddMMyy");
LocalDate date = LocalDate.parse(input, parser);
// locale specific format
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
System.out.println(formatter.format(date));
As this is locale specific, in my system I've got the output:
27/03/17
If you want to use exactly the same pattern produced by GWT, you can use:
// get the GWT format
String pattern = DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT).getPattern();
// use the same format in the formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
System.out.println(formatter.format(date));
Based on the GWT docs, it seems to use patterns compatible with DateTimeFormatter (at least for date fields), so this should work for all cases.
If you want a fixed format (like 03/27/2017), just do:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
Check the javadoc for more details about date patterns.

Get year format from a given Date format

I have a localized date format. I want to retrieve just the year format in Java.
So if I am given mmddyyyy I would like to extract yyyy.
if I am given mmddyy, i would like to extract yy.
I cannot find a way to get that info using SimpleDateFormat, Date, Calendar etc. classes.
It's important to note that the concept of a "year format" only really applies to SimpleDateFormat. (In the default JDK, anyway.) More specifically, SimpleDateFormat is the only DateFormat implementation provided by the JDK that uses the concept of a "format string" that you can pull out a year format from; the other implementations use more opaque mappings from a Date to a String. For this reason, what you're asking for is only well-defined on the SimpleDateFormat class (again, among the DateFormat implementations available in the stock JDK).
If you're working with a SimpleDateFormat, though, you can just pull the year format out with regular expressions:
SimpleDateFormat df=(something);
final Pattern YEAR_PATTERN=Pattern.compile("^(?:[^y']+|'(?:[^']|'')*')*(y+)");
Matcher m=YEAR_PATTERN.matcher(df.toPattern());
String yearFormat=m.find() ? m.group(1) : null;
// If yearFormat!=null, then it contains the FIRST year format. Otherwise, there is no year format in this SimpleDateFormat.
The regular expression looks so strange because it has to ignore any y's that happen in "fancy" quoted parts of the date format string, like "'Today''s date is 'yyyy-MM-dd". Per the comment in the code above, note that this only pulls out the first year format. If you need to pull out multiple formats, you'll just need to use the Matcher a little differently:
SimpleDateFormat df=(something);
final Pattern YEAR_PATTERN=Pattern.compile("\\G(?:[^y']+|'(?:[^']|'')*')*(y+)");
Matcher m=YEAR_PATTERN.matcher(df.toPattern());
int count=0;
while(m.find()) {
String yearFormat=m.group(1);
// Here, yearFormat contains the count-th year format
count = count+1;
}

Localtion of pattern for date formats in java

In java you can get the date format based for a specific locale by doing:
Locale locale = new Locale("en", "UK");
DateFormat format = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
System.out.println( ((SimpleDateFormat)format).toPattern());
This prints
dd-MMM-yyyy
Is this pattern hardcoded in a properties file somewhere? Is there any way I can extend the java mechanism and apply my own pattern (locale dependent) so when I run the above code I get:
dd-MM-yyyy
The idea is to work always with the same format, in my case the DateFormat.SHORT.
I end up using the short format and replacing the default format containing 2 character for the year with 4 characters for the year.
And in case someone want to know, the formats are indeed hardcoded in the package sun.text.resources under the classes FormatData_XX_YY (e.g. FormatData_en_UK).

How can I format date by locale in Java? [duplicate]

This question already has answers here:
SimpleDateFormat and locale based format string
(10 answers)
Closed 8 years ago.
I need to format date to app that has many languages, what is best way to format date, because every country has different kind of date formatting, so is it possible to format date by locale?
Yes, using DateFormat.getDateInstance(int style, Locale aLocale)
This displays the current date in a locale-specific way.
So, for example:
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, yourLocale);
String formattedDate = df.format(yourDate);
See the docs for the exact meaning of the style parameter (SHORT, MEDIUM, etc)
SimpleDateFormat has a constructor which takes the locale, have you tried that?
http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html
Something like
new SimpleDateFormat("your-pattern-here", Locale.getDefault());
Joda-Time
Using the Joda-Time 2.4 library. The DateTimeFormat class is a factory of DateTimeFormatter formatters. That class offers a forStyle method to access formatters appropriate to a Locale.
DateTimeFormatter formatter = DateTimeFormat.forStyle( "MM" ).withLocale( Java.util.Locale.CANADA_FRENCH );
String output = formatter.print( DateTime.now( DateTimeZone.forID( "America/Montreal" ) ) );
The argument with two letters specifies a format for the date portion and the time portion. Specify a character of 'S' for short style, 'M' for medium, 'L' for long, and 'F' for full. A date or time may be ommitted by specifying a style character '-' HYPHEN.
Note that we specified both a Locale and a time zone. Some people confuse the two.
A time zone is an offset from UTC and a set of rules for Daylight Saving Time and other anomalies along with their historical changes.
A Locale is a human language such as Français, plus a country code such as Canada that represents cultural practices including formatting of date-time strings.
We need all those pieces to properly generate a string representation of a date-time value.
Take a look at java.text.DateFormat.
Easier to use (with a bit less power) is the derived class, java.text.SimpleDateFormat
And here is a good intro to Java internationalization: http://java.sun.com/docs/books/tutorial/i18n/index.html (the "Formatting" section addressing your problem, and more).
I agree with Laura and the SimpleDateFormat which is the best way to manage Dates in java. You can set the pattern and the locale. Plus you can have a look at this wikipedia article about Date in the world -there are not so many different ways to use it; typically USA / China / rest of the world -

Categories