17

I am running my Java app on a Windows 7 machine where my regional settings are set up to format dates as YYYY-mm-dd and time as HH:mm:ss (e.g. "2011-06-20 07:50:28"). But when I use DateFormat.getDateTimeInstance().format to format my date I do not see that instead I get "20-Jun-2011 7:50:28 AM". What do I need to do to format dates in the way that my customers have their OS setup to display dates?

Here is what my code in question looks like:

File selGameLastTurnFile = selectedGame.getLastTurn ().getTurnFile ();
Date selGameModifiedDate = new Date (selGameLastTurnFile.lastModified());
if (selectedGame.isYourTurn ())  {
    gameInfo = Messages.getFormattedString ("WhoseTurnIsIt.Prompt.PlayTurn",  //$NON-NLS-1$
            FileHelper.getFileName (selGameLastTurnFile), 
            DateFormat.getDateTimeInstance().format(selGameModifiedDate));
}  else  {
    gameInfo = Messages.getFormattedString ("WhoseTurnIsIt.Prompt.SentTurn",  //$NON-NLS-1$
            selGameLastTurnFile.getName (), 
            DateFormat.getDateTimeInstance().format(selGameModifiedDate));
}

The Messages.getFormattedString calls are using MessageFormat to put the date into a sentence that will look like this:

Play the turn 'QB Nat vs Ian 008' (received 20-Jun-2011 7:50:28 AM)

However my OS settings are setup to format the date as I described above and I expected to see this:

Play the turn 'QB Nat vs Ian 008' (received 2011-06-20 07:50:28)

I searched here and other Java programming sites and could not find the answer but this seems like such an obvious thing to want to do that I feel like I am missing something obvious.

assylias
  • 321,522
  • 82
  • 660
  • 783
Ian Leslie
  • 841
  • 1
  • 9
  • 25
  • For clarification I am trying to get date and time formatting as specified by my customers' OS settings. Many people, myself included, tweak their date, time and currency settings from the locale defaults. I don't want to just get what someone at Oracle things is the way dates should be formatted for a particular locale I want the formatting that my customers have set on their OS. I hope that makes my request more clear. – Ian Leslie Jul 16 '11 at 14:56
  • It's really annoying that my C implementation can do it, but not Java. `strftime("%c")` with locale `""` works perfectly. – aib Sep 12 '11 at 03:01
  • 1
    While using the `DateFormat` class when this question was asked 8 years ago was reasonable, that class is notoriously troublesome and now long outdated. Today you should instead use `DateTimeFormatter` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Apr 02 '19 at 07:42

7 Answers7

10

First you have to tell Java what your system LOCALE looks like.

Check Java System.
String locale = System.getProperty("user.language")

And then format the date accordinly (SimpleDateFormat)
SimpleDateFormat(String pattern, Locale locale)

Refer to the practical Java code for a working example...

String systemLocale = System.getProperty("user.language");
String s;
Locale locale; 

locale = new Locale(systemLocale );
s = DateFormat.getDateInstance(DateFormat.MEDIUM, locale).format(new Date());
System.out.println(s);
// system locale is PT outputs 16/Jul/2011

locale = new Locale("us");
s = DateFormat.getDateInstance(DateFormat.MEDIUM, locale).format(new Date());
System.out.println(s);
// outputs Jul 16, 2011

locale = new Locale("fr");
s = DateFormat.getDateInstance(DateFormat.MEDIUM, locale).format(new Date());
System.out.println(s);
// outputs 16 juil. 2011  
Frankie
  • 24,627
  • 10
  • 79
  • 121
  • Thanks for the way to get the system locale (I understood that if you did not specify the locale the system default would be used). I am trying it now. – Ian Leslie Jul 15 '11 at 20:07
  • Ok what I tried did not work either. I do not want to specify the pattern to use to format the date I want to use the one the user has setup with their OS. I think that is the only reasonable way to go. I have my locale set to English (Canada) and my date and time patterns the way I want set in the OS. My users will have done the same. using `Locale locale = new Locale(System.getProperty ("user.language"), System.getProperty("user.country"));` I can get the correct locale but when I use that with `DateFormat.getDateTimeInstance` I do *not* get the formatting as specified by the OS. – Ian Leslie Jul 15 '11 at 20:24
  • I just switched to using `new SimpleDateFormat().format(selGameModifiedDate)` which says it uses the default pattern for the default locale. But it is *not* using my OS settings. What is the magic here? Surely everyone who programs in Java wants to present the data, time and other items formatted as the user expects based on the OS settings? Thanks for your help - I hope someone has some insight on how to do this. – Ian Leslie Jul 15 '11 at 20:31
  • Thank you for your efforts. I am still not getting what I expect. I took your code example but used `DateFormat.SHORT` instead and I get the output: 7/16/11 7/16/11 16/07/11 But the thing is my default pattern set on my OS is 'yyyy-MM-dd' but I do not get that. What I want to be able to do is get the date formatted the way my customers have specified in their OS. What the code I am using and you have offered is giving me some format that is dictated by the JVM as the format for a particular locale. I am hoping there is a way to get what the OS date format is set to. – Ian Leslie Jul 16 '11 at 14:50
5

Oracle JDK 8 fully supports formatting using user-customized OS regional settings.

Just set system property java.locale.providers=HOST

According to https://docs.oracle.com/javase/8/docs/technotes/guides/intl/enhancements.8.html:

HOST represents the current user's customization of the underlying operating system's settings. It works only with the user's default locale, and the customizable settings may vary depending on the OS, but primarily Date, Time, Number, and Currency formats are supported.

The actual implementation of this formatter is available in the class sun.util.locale.provider.HostLocaleProviderAdapterImpl. If using system property is not acceptable (say, your don't want to affect the whole application), it's possible to use that provider class directly. The class is internal API, but can be reached using reflection:

private static DateFormat getSystemDateFormat() throws ReflectiveOperationException {
        Class<?> clazz = Class.forName("sun.util.locale.provider.HostLocaleProviderAdapterImpl");
        Method method = clazz.getMethod("getDateFormatProvider");
        DateFormatProvider dateFormatProvider = (DateFormatProvider)method.invoke(null);
        DateFormat dateFormat = dateFormatProvider.getDateInstance(DateFormat.MEDIUM, Locale.getDefault(Locale.Category.FORMAT));
        return dateFormat;
    }
zakgof
  • 213
  • 2
  • 8
4

You can't do this in pure Java. There is no way Sun/Oracle could make this system independent.

A quick browse of the .NET libraries gives this page - to quote:

The user might choose to override some of the values associated with the current culture of Windows through the regional and language options portion of Control Panel. For example, the user might choose to display the date in a different format or to use a currency other than the default for the culture. If the CultureInfo.UseUserOverride property is set to true, the properties of the CultureInfo.DateTimeFormat object, the CultureInfo.NumberFormat object, and the CultureInfo.TextInfo object are also retrieved from the user settings.

I would suggest that you do this in a way that is system dependent upon Windows if you need this functionality (e.g. access the Windows registry as @laz suggested).

  • 1
    Actually Sun/Oracle has *chosen* not to do it. They already have system specific JVMs and those JVMs already access the user's locale setting (among others) they just chose not to cover all the bases. Thanks for the information though - frankly that was what I expected. I was hoping that perhaps someone know of a JNI library that will work with at least some platforms. – Ian Leslie Jul 19 '11 at 11:54
  • 1
    @Ian After a bit more research it turns out the feature for user-specified time and date format is supported in more operating systems than I thought. Not all operating systems support it, but it probably wouldn't be too hard for Sun/Oracle to use custom locales on the OS's that do and leave that transparent to the user. –  Jul 20 '11 at 03:28
3

I found this Java utility class by JetBrains that retrieves all the custom locale settings from the OS (both from Windows and Mac) and does the correct formatting for you:

https://github.com/JetBrains/intellij-community/blob/master/platform/util/src/com/intellij/util/text/DateFormatUtil.java

It's under the Apache 2.0 license so you can probably use it in your project.

Allon Guralnek
  • 15,813
  • 6
  • 60
  • 93
3

I looks like you will need to access the Windows registry for this. See this question for various solutions to that read/write to Windows Registry using Java.

Once you choose one of the many methods of accessing the registry you will need to get the correct key from the registry for the format. This document indicates the key to use is HKEY_USERS\.Default\Control Panel\International.

When using GNOME in Linux, you can use the gconftool command similar to the reg command for Windows as mentioned in the prior links about the Windows registry. I see the key /apps/panel/applets/clock_screen0/prefs/custom_format in my configuration, though it is blank since I am using the default:

gconftool -g /apps/panel/applets/clock_screen0/prefs/custom_format

I'm not sure if that is the value you'd want to use for your purposes or not.

On Mac OS, I'm not sure what you would do.

Community
  • 1
  • 1
laz
  • 28,320
  • 5
  • 53
  • 50
  • Lots of good stuff at the link you added - Thanks. However as you might expect it is Windows only:-( It appears that there is no generic solution to this problem. Too bad Sun / Oracle chose not to make this available. – Ian Leslie Jul 19 '11 at 11:59
  • Sorry, I didn't see that you were looking for a cross platform way to do this. – laz Jul 19 '11 at 13:18
  • I am looking but it does not seem that there is one. – Ian Leslie Jul 19 '11 at 14:06
2
java -Djava.locale.providers=HOST,CLDR,COMPAT YourProgram

Date and time formats are part of Java’s locale data. Java can get its locale data from up to four sources. Which ones it uses is controlled by the java.locale.providers system property. Default up to Java 8 was JRE,SPI. From Java 9 it’s CLDR,COMPAT. None of these will get you the date and time data from the operating system, but you can get them by supplying the HOST locale provider, for example as in the command line above. When running your program with this property definition, you may for example have:

    DateTimeFormatter systemFormatter
            = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Africa/Bangui"));
    String formattedDateTime = now.format(systemFormatter);
    System.out.println(formattedDateTime);

This will print the current date and time in the format defined by the underlying operating system. To the extend that the operating system supports it you can vary the length of the output by using format styles FULL, LONG, MEDIUM and SHORT.

For most purposes you will want to have a DateTimeFormatter knowing the format as in the above code. In the rare case where you want to know a format pattern string that is possible too:

    String osFormat = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
            FormatStyle.SHORT, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.getDefault());

The first argument to getLocalizedDateTimePattern is the date format style. The second is the time style.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

Perhaps I'm misunderstanding what you're getting at here but you need to use the Locale.

 DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);

By using Locale you can control what format for what region you're using.

Mech
  • 2,904
  • 3
  • 24
  • 29
  • 2
    Yes, but the locale is something that the user can set in their OS too. Looks like Frankie has a way to get that. Trying his suggestion now... – Ian Leslie Jul 15 '11 at 20:06