20

I need to format the date into a specific string.

I used SimpleDateFormat class to format the date using the pattern "yyyy-MM-dd'T'HH:mm:ssZ" it returns current date as
"2013-01-04T15:51:45+0530" but I need as
"2013-01-04T15:51:45+05:30".

Below is the coding used,

Calendar c = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ENGLISH);      
Log.e(C.TAG, "formatted string: "+sdf.format(c.getTime()));

Output: formatted string: 2013-01-04T15:51:45+0530

I need the format as 2013-01-04T15:51:45+05:30 just adding the colon in between gmt time.

Because I'm working on Google calendar to insert an event, it accepts only the required format which I have mentioned.

Sahil Mahajan Mj
  • 11,033
  • 8
  • 53
  • 100
fargath
  • 7,844
  • 6
  • 24
  • 36
  • I don't think you can with a simpledateformat. So you will need to insert the `:` manually. [Java 7 has introduced the `X` marker](http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html) that has more formatting options than `Z` but it is not available on android (yet?). – assylias Jan 04 '13 at 12:49
  • If formatting manually is the task to be done(in reference to the above comment), you can search for the last `+` and then add a `:` after 2 indices. – Kazekage Gaara Jan 04 '13 at 12:54
  • 1
    @KazekageGaara It could also be a `-`... – assylias Jan 04 '13 at 13:02
  • While in 2013 it was reasonable to use `Calendar` and `SimpleDateFormat`, don’t do that anymore. Those classes are poorly designed and now long outdated, the latter in particular notoriously troublesome. Instead use `OffsetDateTime` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). Or just `OffsetDateTime.toString` and no formatter. – Ole V.V. Mar 21 '19 at 15:10

10 Answers10

35

You can also use "ZZZZZ" instead of "Z" in your pattern (according to documentation). Something like this

    Calendar c = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.ENGLISH);      
    Log.e(C.TAG, "formatted string: "+sdf.format(c.getTime()));
Grimmy
  • 2,041
  • 1
  • 17
  • 26
  • 2
    This is correct answer, @fargath you should mark it up. – VAdaihiep Sep 24 '15 at 09:05
  • 2
    This should be the correct answer. I find it ridiculous when people refer to libraries as a primary solution instead of it being a secondary suggestion. It's like threading cloth with a sword. – humblerookie Aug 12 '16 at 07:13
  • The documentation says it supports X. – rozina Jun 23 '17 at 09:36
  • For me this doesn't work. I get this string: `2018-07-06T11:46:43+0200`. The colon in the timezone is missing. So it's not ISO8601. – toXel Jul 06 '18 at 09:50
  • I fail to see the linked documentation mentioning the possibility of 5 `Z` (`ZZZZZ`). Is that just me? Also on my Java 8 I get `formatted string: 2019-03-21T16:06:30+0100` without colon, but the outcome on Android may be different. – Ole V.V. Mar 21 '19 at 15:07
  • For me, this doesn't work, I have to use `"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"` – Waqar Khan Apr 20 '20 at 12:16
14

You can use Joda Time instead. Its DateTimeFormat has a ZZ format attribute which does what you want.

Link

Big advantage: unlike SimpleDateFormat, DateTimeFormatter is thread safe. Usage:

DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZZ")
    .withLocale(Locale.ENGLISH);
fge
  • 119,121
  • 33
  • 254
  • 329
  • I found a slightly different way of doing this, given the: DateTime my_date = new DateTime(); ... Set the date to something my_date = ... Then format it with: String curr_date = my_date.toLocalDate().toString("yyyy-MM-dd"); – Brandon Jan 23 '15 at 15:53
  • **Update:** The *Joda-Time* framework has been replaced by *java.time* defined in JSR 310. Most of *java.time* functionality is available in all versions of Android with the latest tooling using API "desugaring". See links and more info in [Answer by Live and Let Live](https://stackoverflow.com/a/65708581/642706). – Basil Bourque Jan 15 '21 at 06:38
4

tl;dr

You can use the pattern, yyyy-MM-dd'T'HH:mm:ssXXX for your desired output.

java.time

The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.

Using the modern date-time API:

Building an object that holds date, time and timezone offset information and formatting the same:

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        OffsetDateTime odt = OffsetDateTime.of(LocalDate.of(2013, 1, 4), LocalTime.of(15, 51, 45),
                ZoneOffset.ofHoursMinutes(5, 30));

        // Print the default format i.e. the string returned by OffsetDateTime#toString
        System.out.println(odt);

        // Custom format
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
        System.out.println(dtf.format(odt));
    }
}

Output:

2013-01-04T15:51:45+05:30
2013-01-04T15:51:45+05:30

As you can notice, the outputs for the default format and for that using a DateTimeFormatter are same. However, there is a catch here: the implementation of OffsetDateTime#toString omits the second and the fraction of second if they are 0 i.e. if the time in the above code is LocalTime.of(15, 0, 0), the output for the default format will be 2013-01-04T15:00+05:30. If you need a string like 2013-01-04T15:00:00+05:30 for this time, you will have to use a DateTimeFormatter with the desired pattern.

Parsing and formatting:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtfForInputString = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ", Locale.ENGLISH);
        OffsetDateTime odt = OffsetDateTime.parse("2013-01-04T15:51:45+0530", dtfForInputString);

        // Print the default format i.e. the string returned by OffsetDateTime#toString
        System.out.println(odt);

        // Custom format
        DateTimeFormatter dtfCustomOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
        System.out.println(dtfCustomOutput.format(odt));
    }
}

Output:

2013-01-04T15:51:45+05:30
2013-01-04T15:51:45+05:30

Using the legacy API:

Building a date-time object for the given timezone offset and formatting the same:

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+05:30"));
        calendar.set(2013, 0, 4, 15, 51, 45);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
        Date date = calendar.getTime();
        System.out.println(sdf.format(date));
    }
}

Output:

2013-01-04T15:51:45+05:30

The Calendar class uses UTC (or GMT) as its default timezone and therefore, unless you specify the timezone with it, it will return the java.util.Date object for UTC.

Similarly, the SimpleDateFormat class also uses UTC as its default timezone and therefore, unless you specify the timezone with it, it will return the formatted String for the corresponding date-time in UTC.

Parsing and formatting:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdfForInputString = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ENGLISH);
        Date date = sdfForInputString.parse("2013-01-04T15:51:45+0530");

        SimpleDateFormat sdfCustomOutput = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
        sdfCustomOutput.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
        System.out.println(sdfCustomOutput.format(date));
    }
}

Output:

2013-01-04T15:51:45+05:30
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
1

What you can do is just add the ":" manually using substring(). I have faced this earlier and this solution works.

TechSpellBound
  • 2,505
  • 6
  • 25
  • 36
1

Try this

Calendar c = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ENGLISH);   

System.out.println("formatted string: "+sdf.format(c.getTime()));

String text = sdf.format(c.getTime());  
String result = text.substring(0, 22) + ":" + text.substring(22);  
System.out.println("result = " + result);
Pratik
  • 30,639
  • 18
  • 84
  • 159
Faizan
  • 3,512
  • 2
  • 18
  • 15
1

Why not just do it manually with regexp?

String oldDate = "2013-01-04T15:51:45+0530";
String newDate = oldDate.replaceAll("(\\+\\d\\d)(\\d\\d)", "$1:$2");

Same result, with substring (if performance is an issue).

String oldDate = "2013-01-04T15:51:45+0530";
int length = oldDate.length();
String newDate = oldDate.substring(0, length - 2) + ':' + oldDate.substring(length - 2);
Gal
  • 5,338
  • 5
  • 33
  • 55
1

If you want the date for a different timeZone (which the title suggests)

  val nowMillsUTC = System.currentTimeMillis()

  val timeZoneID = "Australia/Perth"
  val tz = TimeZone.getTimeZone(timeZoneID)

  val simpleDateFormat = SimpleDateFormat("HH.mm  dd.MMM.yyyy", Locale.getDefault())
  simpleDateFormat.setTimeZone(tz)
  val resultTxt = simpleDateFormat.format(nowMillsUTC)

  print(timeZoneID + " -> " + resultTxt)
  //   Australia/Perth -> 19.59  21.Mar.2019
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Dan Alboteanu
  • 9,404
  • 1
  • 52
  • 40
  • 1
    Apart from `SimpleDateFormat` and `TimeZone` being poorly designed and long outdated: On my Java 8 `TimeZone.getAvailableIDs()[358]` is `Australia/Yancowinna`, and who knows what it will be in future Java versions? I wouldn’t be too sure about Android either, but haven’t tried. – Ole V.V. Mar 21 '19 at 13:00
  • you are right - the getAvailableID's is unreliable. I edited accordingly – Dan Alboteanu Mar 21 '19 at 14:52
0

Try this code

Calendar c = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss Z", Locale.ENGLISH);
String s = sdf.format(c.getTime());
String fDate = s.substring(0, s.length()-2) +":"+s.substring(s.length()-2, s.length());
Log.e("check", "formatted string: "+fDate);
Pratik
  • 30,639
  • 18
  • 84
  • 159
0

This is how i do it on android Build.VERSION.SDK_INT < 26

int offset = TimeZone.getDefault().getRawOffset();
String str_date='20:30 12-01-2021';
DateFormat formatter = new SimpleDateFormat("HH:mm dd-MM-yyy",Locale.US);
Date date = formatter.parse(str_date);
long utcTime = date.getTime() + (3600000*3);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm dd/MM/yyyy", Locale.US);
String dateStr = sdf.format(utcTime + offset);
System.out.println(dateStr);

As my server sends the time with -3 timezone i have to add (3600*3) to getTime and i save it into utcTime, this way utcTime is in UTC. And then i add to utcTime the offset of the phone current timezone. In my case as my timezone is -3 its prints:

20:30 12/01/2021

But if i change my time zone the date also changes.

I already answer it here to: Convert UTC into Local Time on Android

user3486626
  • 139
  • 1
  • 6
-1

Simply refactor this code and replace the 'Locale.getDefault()' with the Locale you need

private SimpleDateFormat getDateFormat() {
    SimpleDateFormat dateFormat = (SimpleDateFormat) SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.DEFAULT, Locale.getDefault());
    String pattern = dateFormat.toLocalizedPattern();
    pattern = pattern.trim();
    dateFormat.applyLocalizedPattern(pattern);
    return dateFormat;
}

//And here is the usage

SimpleDateFormat sdf = getDateFormat();

sdf.format(new Date());

user2288580
  • 2,210
  • 23
  • 16