25

I'm trying to format date from java.util.Date. I need this format:

2016-06-10T13:38:13.687+02:00.

How correctly convert this from standard Date format

May 04 09:51:52 CDT 2009 ?

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss z", Locale.getDefault());
sdf.format(new Date());

This code unfortunately return value without +02:00.

SCouto
  • 7,808
  • 5
  • 32
  • 49
Algeroth
  • 785
  • 3
  • 12
  • 29
  • 1
    Just to set the usage straight: +02:00 is not a time zone, it’s a UTC offset. Africa/Cairo is a time zone, and Easter European Time may pass as one. A time zone contains the historic and known future changes in UTC offset used by the people in the zone. – Ole V.V. Feb 28 '18 at 09:48
  • As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends, and adding [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project in order to use `java.time`, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Feb 28 '18 at 09:48

6 Answers6

26

As per the standard Java docs: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

for getting date and time formatting of

2001-07-04T12:08:56.235-07:00


You Need to use below String pattern:

"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"

So with below code, you can get what you want:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.getDefault());
    simpleDateFormat .format(new Date());
Shridutt Kothari
  • 7,326
  • 3
  • 41
  • 61
25

Just turn your z to upperCase

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss Z", Locale.getDefault());
    sdf.format(new Date());

Result: 2016-06-10T13:53:22 +0200

SCouto
  • 7,808
  • 5
  • 32
  • 49
  • 16
    @Algeroth you accepted this answer but you posted in question that you wanted '2016-06-10T13:38:13.687+02:00' not the '2016-06-10T13:53:22 +0200' – Shridutt Kothari Jun 10 '16 at 15:47
6

Time for someone to provide the modern answer.

    OffsetDateTime now = OffsetDateTime.now(ZoneId.of("Africa/Cairo"));
    String formatted = now.toString();
    System.out.println(formatted);

This just printed

2018-02-28T16:42:59.628526+02:00

Edit: I asked for 3 decimals on the seconds, not 6. To exercise more control over the format, use an explicit formatter:

    DateTimeFormatter formatterWithThreeDecimals
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXXXX");
    String formatted = now.format(formatterWithThreeDecimals);
    System.out.println(formatted);

This printed (at time of my edit):

2018-04-30T15:47:41.749+02:00

Please substitute your desired time zone if it didn’t happen to be Africa/Cairo. Specify ZoneId.systemDefault() for your JVM’s time zone setting. The setting can be changed any time by another part of your program or another program running in the same JVM.

Using java.time, the modern Java date and time API, in case you just want an utput that conforms with ISO 8601 and don’t care how many decimals (or whether seconds are printed if they are 0), we don’t need an explicit formatter at all. Your desired string is in ISO 8601 format, the standard format that the modern classes’ toString methods produce. Depending on what you need it for, the result of toString will probably accepted.

The classes you were using, Date and SimpleDateFormat, are long outdated, and the latter in particular notoriously troublesome. I recommend you avoid them and use the modern API instead. It is so much nicer to work with.

If you got a java.util.Date from a legacy API that you don’t want to change just now, convert it to a modern Instant and do further conversions from there. In Java 8 and later this happens like this:

    ZonedDateTime dateTime = oldfashionedDateFromLegacyApi.toInstant()
            .atZone(ZoneId.of("Africa/Cairo"));
    String formatted = dateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);

If you are using ThreeTen Backport and/or ThreeTenABP, the conversion happens a little differently, like this:

    ZonedDateTime dateTime = DateTimeUtils.toInstant(oldfashionedDateFromLegacyApi)
            .atZone(ZoneId.of("Africa/Cairo"));

Again, if you want close control over the output format, don’t use DateTimeFormatter.ISO_OFFSET_DATE_TIME since it will output anything from 1 through 9 decimals and may also leave out the seconds if they are 0. Instead use my formatterWithThreeDecimals from above.

Question: Can I use java.time on Android?

Yes, java.time works nicely on Android. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • I would strongly advise against using ```toString``` to format anything, especially dates and times, in most cases. Even the JavaDoc says that it will use one of 5 different time formats, whichever results in the most concise string representation. If you want to format a date or time, use a formatter. Also with the new API. – David Tanzer Apr 30 '18 at 12:23
  • Thanks for the edit, undid my downvote because now your answer is comprehensive and *also* answers the original question. – David Tanzer Apr 30 '18 at 14:21
4

You just made a simple mistake, You need to use a capital z. What You need is:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss z Z", Locale.getDefault());

in addition to your lower case z. A lower case z gives you just the time zone, but the capital one gives you the time zone based on RFC 822.

EDIT

If you not want a usual time zone, only need +2:00 without for example PST, you only need a capital Z:

   SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss Z", Locale.getDefault());

From the (very simple understandable) Docs:

z/zz/zzz:PST zzzz:Pacific Standard Time
Z/ZZ/ZZZ:-0800 ZZZZ:GMT-08:00 ZZZZZ:-08:00
Opiatefuchs
  • 9,800
  • 2
  • 36
  • 49
3

Add SSSZ in the format

"yyyy-MM-dd'T'HH:mm:ss z" => "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

Just change this line

Old: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss z", Locale.getDefault()); sdf.format(new Date());

New: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault());

TechnoTech
  • 744
  • 4
  • 14
2

You have add (ZZZZZ) at the end to get this format like below

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss ZZZZZ", Locale.getDefault());
Raja Jawahar
  • 6,742
  • 9
  • 45
  • 56