19

I have a string in the pattern yyyy-MM-dd hh:mm a and i can get the time zone object separately in which the above string represents the date.

I want to convert this to the below format. yyyy-MM-dd HH:mm:ss Z

How can i do this?

John
  • 2,682
  • 5
  • 23
  • 24
  • http://joda-time.sourceforge.net/ makes all date manipulations in java much much easier – NimChimpsky Nov 17 '10 at 11:09
  • @Emil i got to know this feature after you said :), Thanks. – John Nov 17 '10 at 11:41
  • 1
    FYI, the [Joda-Time](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the [java.time](http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) classes. – Basil Bourque Jan 22 '17 at 21:47

6 Answers6

26

You can use SimpleDateFormat with yyyy-MM-dd HH:mm:ss and explicitly set the TimeZone:

public static Date getSomeDate(final String str, final TimeZone tz)
    throws ParseException {
  final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm a");
  sdf.setTimeZone(tz);
  return sdf.parse(str);
}

/**
 * @param args
 * @throws IOException
 * @throws InterruptedException
 * @throws ParseException
 */
public static void main(final String[] args) throws ParseException {
  final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
  System.out.println(sdf.format(getSomeDate(
      "2010-11-17 01:12 pm", TimeZone.getTimeZone("Europe/Berlin"))));
  System.out.println(sdf.format(getSomeDate(
      "2010-11-17 01:12 pm", TimeZone.getTimeZone("America/Chicago"))));
}

Prints out:

2010-11-17 13:12:00 +0100

2010-11-17 20:12:00 +0100

Update 2010-12-01: If you want to explicitly printout a special TimeZone, set it in the SimpleDateFormat:

sdf.setTimeZone(TimeZone .getTimeZone("IST")); 
System.out.println(sdf.format(getSomeDate(
    "2010-11-17 01:12 pm", TimeZone.getTimeZone("IST"))));

Which prints 2010-11-17 13:12:00 +0530

Community
  • 1
  • 1
Michael Konietzka
  • 5,419
  • 2
  • 28
  • 29
  • Thanks Mr.Michael, The date & time gets changed according to the Timezone.Note down the +100, it doesn't changes the TIMEZONE offset – John Nov 18 '10 at 11:37
  • @shal: Sorry, I do not understand your second sentence. Do you think something is wrong? – Michael Konietzka Nov 18 '10 at 11:55
  • @ Michael, I am saying the time is getting converted properly but see the "Z" part in the date values printed "+0100" it doesn't changes.For eg if i am converting a date from GMT to IST then the "Z" part of the converted date must be "+0530". – John Dec 01 '10 at 10:24
  • This depends on the system the code is running. For `IST` it prints out `2010-11-17 07:42:00 +0000` on ideone. – Michael Konietzka Dec 01 '10 at 10:55
  • @shal: Distinguish between the generation of a valid date with an explicit TimeZone set when parsing and the printout of the date with a explicit TimeZone. – Michael Konietzka Dec 01 '10 at 11:15
  • 1
    FYI, the old [`Calendar`](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html) and [`Date`](http://docs.oracle.com/javase/8/docs/api/java/util/Date.html) classes are now [legacy](https://en.wikipedia.org/wiki/Legacy_system). Supplanted by the [java.time](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) classes. – Basil Bourque Jan 22 '17 at 21:48
  • I recommend you don’t use `SimpleDateFormat`, `TimeZone` and `Date`. Those classes are poorly designed and long outdated, the first in particular notoriously troublesome. Instead use `LocalDateTime`, `ZoneId`, `DateTimeFormatter` and other classes from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). See [the answer by Basil Bourque](https://stackoverflow.com/a/41796443/5772882). – Ole V.V. Sep 04 '19 at 10:49
15

tl;dr

LocalDateTime.parse(                        // Parse string as value without time zone and without offset-from-UTC.
    "2017-01-23 12:34 PM" , 
    DateTimeFormatter.ofPattern( "uuuu-MM-dd hh:mm a" )
)                                           // Returns a `LocalDateTime` object.
.atZone( ZoneId.of( "America/Montreal" ) )  // Assign time zone, to determine a moment. Returns a `ZonedDateTime` object.
.toInstant()                                // Adjusts from zone to UTC.
.toString()                                 // Generate string: 2017-01-23T17:34:00Z
.replace( "T" , " " )                       // Substitute SPACE for 'T' in middle.
.replace( "Z" , " Z" )                      // Insert SPACE before 'Z'.

Avoid legacy date-time classes

The other Answers use the troublesome old date-time classes (Date, Calendar, etc.), now legacy, supplanted by the java.time classes.

LocalDateTime

I have a string in the pattern yyyy-MM-dd hh:mm a

Such an input string lacks any indication of offset-from-UTC or time zone. So we parse as a LocalDateTime.

Define a formatting pattern to match your input with a DateTimeFormatter object.

String input = "2017-01-23 12:34 PM" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd hh:mm a" );
LocalDateTime ldt = LocalDateTime.parse( input , f );

ldt.toString(): 2017-01-23T12:34

Note that a LocalDateTime is not a specific moment, only a vague idea about a range of possible moments. For example, a few minutes after midnight in Paris France is still “yesterday” in Montréal Canada. So without the context of a time zone such as Europe/Paris or America/Montreal, just saying “a few minutes after midnight” has no meaning.

ZoneId

and i can get the time zone object separately in which the above string represents the date.

A time zone is represented by the ZoneId class.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" );

ZonedDateTime

Apply the ZoneId to get a ZonedDateTime which is indeed a point on the timeline, a specific moment in history.

ZonedDateTime zdt = ldt.atZone( z );

zdt.toString(): 2017-01-23T12:34-05:00[America/Montreal]

Instant

I want to convert this to the below format. yyyy-MM-dd HH:mm:ss Z

First, know that a Z literal character is short for Zulu and means UTC. In other words, an offset-from-UTC of zero hours, +00:00.

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).

You can extract a Instant object from a ZonedDateTime.

Instant instant = zdt.toInstant();  // Extracting the same moment but in UTC.

To generate a string in standard ISO 8601 format, such as 2017-01-22T18:21:13.354Z, call toString. The standard format has no spaces, uses a T to separate the year-month-date from the hour-minute-second, and appends the Z canonically for an offset of zero.

String output = instant.toString();

instant.toString(): 2017-01-23T17:34:00Z

I strongly suggest using the standard formats whenever possible. If you insist on using spaces as in your stated desired format, either define your own formatting pattern in a DateTimeFormatter object or just do a string manipulation on the output of Instant::toString.

String output = instant.toString()
                       .replace( "T" , " " )  // Substitute SPACE for T.
                       .replace( "Z" , " Z" ); // Insert SPACE before Z.

output: 2017-01-23 17:34:00 Z

Try this code live at IdeOne.com.


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, & SimpleDateFormat.

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

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?

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
5

Use SimpleDateFormat

String string1 = "2009-10-10 12:12:12 ";
SimpleDateFormat sdf =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z")
sdf.setTimeZone(tz);
Date date = sdf.parse(string1);
jmj
  • 237,923
  • 42
  • 401
  • 438
1

Undoubtedly, the format which is generally used will be of a form 2014-10-05T15:23:01Z (TZ)

For that one has to use this code

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
String dateInString = "2014-10-05T15:23:01Z";

 try {

     Date date = formatter.parse(dateInString.replaceAll("Z$", "+0000"));
     System.out.println(date);

 } catch (ParseException e) {
     e.printStackTrace();
 }

Its output will be Sun Oct 05 20:53:01 IST 2014

However, I am not sure why we had to replaceAll "Z" if you do not add replaceAll the program will fail.

Somum
  • 2,382
  • 26
  • 15
  • Just a note on the replaceAll() comment in your answer. replace() works with string literals where as replaceAll() or replaceFirst() supports a regular expression. If you did replace("Z", "+0000"), that should give you the same result as your replaceAll("Z$", "+0000") – Jason Slobotski Jul 19 '18 at 21:24
0

Create a new instance of SimpleDateFormat using your date pattern. Afterwards you can call it's parse method to convert date strings to a java.util.Date object.

Matt
  • 74,352
  • 26
  • 153
  • 180
Robert
  • 39,162
  • 17
  • 99
  • 152
0

Please try this for the format "yyyy-MM-dd HH:mm:ss Z", Eg: "2020-12-11 22:59:59 GMT", you can use different time zones like PST, GMT, etc.

PMFrank
  • 1
  • 1