33

I'm new to both Java and Android development so this might be a stupid question, but I've been searching for days now and can't find a solution:

I try to output a java.util.Date depending on the user's locale.

Searching on StackOverflow lead me to this:

java.util.Date date = new Date();
String dateString = DateFormat.getDateFormat(getApplicationContext()).format(date);

This outputs:

20/02/2011

On my french localized phone. Almost fine.

How can I also output the hours, minutes and seconds parts of the Date, using the user's locale ? I've been looking in the android documentation but couldn't find anything.

Many thanks.

ereOn
  • 53,676
  • 39
  • 161
  • 238

6 Answers6

34

Use android.text.format.DateFormat.getTimeFormat()

ref: http://developer.android.com/reference/android/text/format/DateFormat.html

Avinash R
  • 3,101
  • 1
  • 27
  • 47
Tiago
  • 1,337
  • 11
  • 17
18

tl;dr

ZonedDateTime                                   // Represent a moment as seen in the wall-clock time used by the people of a particular region (a time zone). 
.now( ZoneId.of( "Asia/Kolkata" ) )             // Capture the current moment as seen in the specified time zone. Returns a `ZonedDateTime` object.
.format(                                        // Generate text representing the value of this `ZonedDateTime` object.
    DateTimeFormatter                           // Class controlling the generation of text representing the value of a date-time object.
    .ofLocalizedDateTime ( FormatStyle.FULL )   // Automatically localize the string representing this date-time value.
    .withLocale ( Locale.FRENCH )               // Specify the human language and cultural norms used in localizing.
)                                               // Return a `String` object.

java.time

The code in the Question uses troublesome old date-time classes, now legacy, supplanted by the java.time classes built into Java 8 and later.

Locale and time zone have nothing to do with each other. Locale determines the human language and cultural norms used when generating a String to represent a date-time value. The time zone determines the wall-clock time of a particular region used to represent a moment on the timeline.

The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant instant = Instant.now();

2016-10-12T07:21:00.264Z

Apply a time zone to get a ZonedDateTime. I arbitrarily choose to show this moment using India time zone. Same moment, same point on the timeline.

ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = instant.atZone( z );

2016-10-12T12:51:00.264+05:30[Asia/Kolkata]

Generate a String using the locale of Québec Canada. Let java.time automatically localize the string.

Locale l = Locale.CANADA_FRENCH;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.FULL ).withLocale ( l );
String output = zdt.format ( f );  // Indian time zone with Québécois presentation/translation.

mercredi 12 octobre 2016 12 h 51 IST


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to java.time.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

  • Java SE 8 and SE 9 and later
  • Built-in.
  • Part of the standard Java API with a bundled implementation.
  • Java 9 adds some minor features and fixes.
  • Java SE 6 and SE 7
  • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
  • The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
  • See How to use….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Diagram showing when to use java.time, ThreeTenABP, or Android desugaring API

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • "You are using troublesome old date-time classes" Well to be fair, I did ask the question in 2011. Thanks for following up though. You may want to edit the answer to make it clear that things have changed nowadays. As it stands it reads as if using those classes was the wrong thing to do back then which may confuse people. – ereOn Oct 12 '16 at 12:23
  • 1
    Thank you for this well written and conclusive response. – Hank Dec 16 '16 at 15:36
  • @ereOn No criticism was intended, nor likely to be inferred by any reader. The dates of all posts are clearly stated, so the age of a post is obvious and the context clear. Indeed, my use of the word “now” in the very first sentence suggests the gap in time between your Question and my Answer. Every programmer knows the information technology is fast-moving and always changing. – Basil Bourque Sep 09 '19 at 22:56
  • That's fine. I saw you edited the question to make the tone less "pedantic" & personal, which is definitely better. I appreciate it. Glad we all learned something in the process. Thanks for your answer! – ereOn Sep 19 '19 at 11:36
  • this java sdk and most of that available from 26 API on Android only, such a bad answer, and it's copied from another question which is not related to Android – user924 Nov 29 '20 at 16:29
  • @user924 Regarding your comment about *java.time* functionality being available only on Android 26 and later, you are incorrect. I suggest you reread the bullets at the end of my Answer. And I have added a diagram at the bottom to aid in your understanding. – Basil Bourque Nov 30 '20 at 05:01
  • @user924 Regarding your comment about similarities to posting on another Question not related to Android, brace yourself as this may be a shock: *Android uses Java*. The code and concepts regarding date-time handling and using *java.time* will indeed be similar when used on plain Java and when used on Android. – Basil Bourque Nov 30 '20 at 05:05
  • `brace yourself as this may be a shock: Android uses Java` are you trying to joke here?) – user924 Nov 30 '20 at 11:21
9

java.text.DateFormat has all the functions you could possibly need:

DateFormat.getDateInstance()

DateFormat.getTimeInstance()

But the one you need is:

DateFormat.getDateTimeInstance() You can also specify the length of the date / time part and the locale. The end result would be:

DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT, Locale.FRENCH).format(Date);

Source: http://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html

Cristan
  • 12,083
  • 7
  • 65
  • 69
5

Use getBestDateTimePattern()

DateFormat.getBestDateTimePattern() from android.text.format package creates the best possible date and time according to the locale set by the user.

For example: the skeleton EEEE, MMM d, YYYY, jj:mm returns localized date and time as follows.

Locale English (India):            Monday 9 Sep 2019, 9:33 PM
Locale English (United States):    Monday, Sep 9, 2019, 9:33 PM
Locale español (Estados Unidos):   lunes, 9 de sep. de 2019 9:33 PM
Locale español (México):           lunes, 9 de sep de 2019 21:33
Locale français (France):          lundi 9 sept. 2019 à 21:33
Locale português (Brasil):         segunda-feira, 9 de set de 2019 21:33

and so on for different locales. It also respects the 12 hour or 24 hour time format of the locale.

For customizing your own skeleton refer to UTS #35 pattern on unicode.org.

Sample Code

Here's the tested sample code in Kotlin:

val skeleton = DateFormat.getBestDateTimePattern(Locale.getDefault(), "EEEE, MMM d, YYYY, jj:mm")
val formatter = SimpleDateFormat(skeleton, Locale.getDefault()).apply {
    timeZone = TimeZone.getDefault()
    applyLocalizedPattern(skeleton)
}
val dateTimeText = formatter.format(calendar.time)
Log.d("YourClass", "Locale ${Locale.getDefault().displayName}: $dateTimeText")

Instead of Calendar class, you can also use ZonedDateTime. Just convert it to Date object and give it to format(). For example: Date(zonedDateTime.toInstant().toEpochMilli())

Hope that helps.

Community
  • 1
  • 1
Yogesh Umesh Vaity
  • 41,009
  • 21
  • 145
  • 105
3

DateFormat.getTimeInstance() gets the time formatter with the default formatting style for the default locale. You can also pass a style and a Locale.

1
public static String formatDate(Date date, boolean withTime)
{
    String result = "";
    DateFormat dateFormat;

    if (date != null)
    {
        try
        {
            String format = Settings.System.getString(context.getContentResolver(), Settings.System.DATE_FORMAT);
            if (TextUtils.isEmpty(format))
            {
                dateFormat = android.text.format.DateFormat.getDateFormat(context);
            }
            else
            {
                dateFormat = new SimpleDateFormat(format);
            }
            result = dateFormat.format(date);

            if (withTime)
            {
                dateFormat = android.text.format.DateFormat.getTimeFormat(context);
                result += " " + dateFormat.format(date);
            }
        }
        catch (Exception e)
        {
        }
    }

    return result;
}
Ivan Kocic
  • 11
  • 2