I am trying to convert datetime in a string to an Instant instance using Java 8 or a utilities package.
For example,
String requestTime = "04:30 PM, Sat 5/12/2018";
to
Instant reqInstant should result in 2018-05-12T20:30:00.000Z
reqString is in the America/Toronto time zone.
This is what I tried
String strReqDelTime = "04:30 PM, Sat 5/12/2018";
Date date = new SimpleDateFormat("hh:mm a, EEE MM/dd/yyyy").parse(requestTime);
Instant reqInstant = date.toInstant();
The above code results in "2018-05-12T23:30:00Z".
How can I do it?
tl;dr
Fix your formatting pattern for unpadded month and day.
Use only java.time classes, never the legacy classes.
Contrived example:
LocalDateTime.parse( // Parse as an indeterminate `LocalDate`, devoid of time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline.
"04:30 PM, Sat 5/12/2018" , // This input uses a poor choice of format. Whenever possible, use standard ISO 8601 formats when exchanging date-time values as text. Conveniently, the java.time classes use the standard formats by default when parsing/generating strings.
DateTimeFormatter.ofPattern("hh:mm a, EEE M/d/uuuu", Locale.US) // Use single-character `M` & `d` when the number lacks a leading padded zero for single-digit values.
) // Returns a `LocalDateTime` object.
.atZone( // Apply a zone to that unzoned `LocalDateTime`, giving it meaning, determining a point on the timeline.
ZoneId.of("America/Toronto") // Always specify a proper time zone with `Contintent/Region` format, never a 3-4 letter pseudo-zone such as `PST`, `CST`, or `IST`.
) // Returns a `ZonedDateTime`. `toString` → 2018-05-12T16:30-04:00[America/Toronto].
.toInstant() // Extract a `Instant` object, always in UTC by definition.
.toString() // Generate a String in standard ISO 8601 format representing the value within this `Instant` object. Note that this string is *generated*, not *contained*.
2018-05-12T20:30:00Z
Use single-digit formatting pattern
You used MM in your formatting pattern, to mean any single-digit value (months January-September) will appear with a padded leading zero.
But your input lacks that padded leading zero. So use a single M.
Ditto for day-of-month I expect: d rather than dd.
Use only java.time
You are using troublesome flawed old date-time classes (Date & SimpleDateFormat) that were supplanted years ago by the java.time classes. The new classes entirely supplant the old. There isn't any need to mix the legacy and modern.
LocalDateTime
Parse as a LocalDateTime because your input string lacks any indicator of time zone or offset-from-UTC. Such a value is not a moment, and it is not a point on the timeline. It is only a set of potential moments along a range of about 26-27 hours.
String input = "04:30 PM, Sat 5/12/2018";
DateTimeFormatter f = DateTimeFormatter.ofPattern("hh:mm a, EEE M/d/uuuu", Locale.US); // Specify locale to determine human language and cultural norms used in translating that input string.
LocalDateTime ldt = LocalDateTime.parse(input, f);
ldt.toString(): 2018-05-12T16:30
ZonedDateTime
If you know for certain that input was intended to represent a moment using the wall-clock time used by the people of the Toronto Canada region, apply a ZoneId to get a ZonedDateTime object.
Assigning a time zone gives meaning to your unzoned LocalDateTime. Now we have a moment, a point on the timeline.
ZoneId z = ZoneId.of("America/Toronto");
ZonedDateTime zdt = ldt.atZone(z); // Give meaning to that `LocalDateTime` by assigning the context of a particular time zone. Now we have a moment, a point on the timeline.
zdt.toString(): 2018-05-12T16:30-04:00[America/Toronto]
Instant
To see that same moment as UTC, extract an Instant. Same moment, different wall-clock time.
Instant instant = zdt.toInstant();
instant.toString(): 2018-05-12T20:30:00Z
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.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. There isn't any need for strings or for java.sql.* classes.
Where can we obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, 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 Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
It seems like the time zone on your computer (server) is US Pacific DST (PDT, GMT-7), but you expect to have the result for US Eastern DST (EDT, GMT-4).
Instant.toString() returns UTC (GMT+0) DateTime in ISO 8601 format. ('Z' at the end means UTC).
SimpleDateFormat treats DateTime String in the default time zone of the computer when it is not specified. And your input does not specify a time zone.
So, you need to do something about in what time zone your input is.
PS.: On my machine in Eastern DST, your code gives me the result exactly as you expected.
For the description, you can read Convert String to Date in Java.
String requestTime = "04:30 PM, Sat 5/12/2018 America/Toronto";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a, EEE M/dd/yyyy z");
ZonedDateTime zonedDateTime = ZonedDateTime.parse(requestTime, formatter);
System.out.println(zonedDateTime.toInstant());
What went wrong in your attempt?
The SimpleDateFormat uses the system's time-zone by default while you have mentioned that requestTime is in America/Toronto timezone. You should never rely on the default time-zone because when your code will be run on a machine in different time-zone your application may behave in an unexpected manner.
How should you have done it?
Set the time-zone to America/Toronto before parsing. Also, Never use Date-Time formatting/parsing API without a Locale.
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
String requestTime = "04:30 PM, Sat 5/12/2018";
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm a, EEE MM/dd/yyyy", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("America/Toronto"));
Date date = sdf.parse(requestTime);
Instant reqInstant = date.toInstant();
System.out.println(reqInstant);
}
}
Output:
2018-05-12T20:30:00Z
Do not pollute the clean java.time API with the error-prone java.util API
The java.time API introduced with Java-8 (March 2014) supplants the error-prone and outdated java.util and their formatting API, SimpleDateFormat. It is recommended to stop using the legacy date-time API and switch to the modern date-time API. You tried parsing the date-time string using the legacy API and then switching to the modern API using Date#toInstant while you could have done everything using the modern API.
You should use Date#toInstant to switch to the modern API if you are using an old code/library that uses java.util.Date.
Solution using the modern date-time API
Parse the date-time string to LocalDateTime as it does not have time-zone → Convert the obtained LocalDateTime into ZonedDateTime of the given time-zone → Convert the obtained ZonedDateTime into Instant.
Demo:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String requestTime = "04:30 PM, Sat 5/12/2018";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("h:m a, EEE M/d/u", Locale.ENGLISH);
// Parse the date-time string to LocalDateTime as it does not have time-zone
LocalDateTime ldt = LocalDateTime.parse(requestTime, dtf);
// Convert the LocalDateTime into ZonedDateTime of the given time-zone
ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/Toronto"));
// Convert the ZonedDateTime into Instant
Instant instant = zdt.toInstant();
System.out.println(instant);
}
}
Output:
2018-05-12T20:30:00Z
Note that I prefer u to y with DateTimeFormatter.
An alternative solution using the modern date-time API
You can convert the obtained LocalDateTime directly into an Instant using LocalDateTime#toInstant by supplying it with the time-zone ID.
Instant instant = ldt.toInstant(ZoneId.of("America/Toronto").getRules().getOffset(ldt));
Learn more about the the modern date-time API from Trail: Date Time.
Instant.parse(String) appropriately formatted
Related
I have to call a web service which is expecting a Date field but they want it in the following format YYYY-MM-DDThh:mm:ss.sssZ. How can I do this?
I tried the following
OffsetDateTime transactionTime = OffsetDateTime.now(ZoneOffset.UTC);
Date.from(transactionTime.toInstant());
but this didn't work. transactionTime is 2021-06-01T15:11:09.942843400Z, but Date.from converts it to Tue Jun 01 11:11:09 EDT 2021.
BTW, I'm using Java 11
Instant.now().toString()
See that code run live at IdeOne.com.
2021-06-01T15:21:16.783779Z
That format is defined in the ISO 8601 standard. The Z on end means an offset-from-UTC of zero hours-minutes-seconds. Pronounced “Zulu”.
Use java.time.Instant to represent a moment as seen in UTC.
Going the other direction, from text to object.
Instant.parse( "2021-06-01T15:21:16.783779Z" )
If you want only milliseconds, you can lop off any microseconds and nanoseconds by truncating.
Instant.now().truncatedTo( ChronoUnit.MILLIS ) ;
Never use the legacy Date class. Use only the java.time classes.
Use DateTimeFormatter to format the Date-Time object
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
OffsetDateTime transactionTime = OffsetDateTime.now(ZoneOffset.UTC);
String formatted = transactionTime.format(dtf);
System.out.println(formatted);
}
}
Output:
2021-06-01T15:49:45.198Z
Learn more about the modern Date-Time API from Trail: Date Time.
What if I want to use java.util.Date?
For any reason, if you need to convert this object of OffsetDateTime to an object of java.util.Date, you can do so as follows:
Date date = Date.from(transactionTime.toInstant());
Note that a java.util.Date object is not a real Date-Time object like the modern Date-Time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since Date does not have timezone information, it applies the JVM's timezone to return the value of Date#toString in the format, EEE MMM dd HH:mm:ss z yyyy calculated from this milliseconds value. If you need to print the Date-Time in a different format and timezone, you will need to use a SimpleDateFormat with the desired format and the timezone set to the applicable one e.g.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDate = sdf.format(date);
System.out.println(strDate);
Output:
2021-06-01T15:49:45.198Z
Some other important notes:
The java.util Date-Time API 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*.
Most of the symbols that you have used in YYYY-MM-DDThh:mm:ss.sssZ are wrong. Check the description of the symbols from the documentation pages of DateTimeFormatter and SimpleDateFormat.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
I converted a date string to Date by SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(DateinString).
Here instead of converting to UTC it is converting to my Local TimeZone. I checked it by displaying this parsed date through format method of DateFormat.
So I have to re format it back to UTC.Now when I am trying to display this parsed date to UTC TimeZone through the same format method, it is still displaying in local TimeZone. Following is my code to format the parsed date to UTC-
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.setTime(alreadyParsedDateTime); //
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(cal.getTime()));
My sample date string is "2015-12-23T15:00:00-0800"
After parse -- alreadyParsedDateTime.toString():: Thu Dec 24 04:30:00 IST 2015
After parse --
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(alreadyParsedDateTime)):: 2015-12-24T04:30:00
After the above mentioned re format of the parsed date to UTC --
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(cal.getTime())):: 2015-12-24T04:30:00
Expected date format is:: 2015-12-23T23:00:00
I don't know why the format method not working in an expected way or there is any trick to do the same. Kindly help..
There are two different topics here; parsing and formatting.
1. Parsing
SimpleDateFormat.parse() will try to parse the timezone from the supplied date string. If the date string you are parsing does not include an explicit timezone, then the "default" timezone on the SimpleDateFormat object will be used. You can set the default time zone with the setTimeZone() method. Please see the API docs for SimpleDateFormat.parse() and DateFormat.setTimeZone() for reference.
Here is an example that shows how the parsing is influenced by the timezone set with setTimeZone():
String dateString = "2015.12.10 13:58:18";
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdf1.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date1 = sdf1.parse(dateString);
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdf2.setTimeZone(TimeZone.getTimeZone("EST"));
Date date2 = sdf2.parse(dateString);
// Shows that the parsing honours time zone -- will print:
// Thu Dec 10 14:58:18 CET 2015 (original date was parsed as GMT)
// Thu Dec 10 19:58:18 CET 2015 (original date was parsed as EST)
System.out.println(date1);
System.out.println(date2);
2. Formatting
Assuming that the date has been parsed correctly, then your problem is with the formatting. You need to set the timezone for the actual SimpleDateFormat object that you are using for formatting. I modified your code to do this and it will now print what you expet:
Calendar cal = Calendar.getInstance();
cal.setTime(alreadyParsedDateTime);
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
sdf3.setTimeZone(TimeZone.getTimeZone("UTC"));
// Prints: 2015-12-23T23:00:00 for your example date string
System.out.println(sdf3.format(cal.getTime()));
tl;dr
Current moment in UTC.
Instant.now() // Capture current moment in UTC.
.toString() // Generate string in standard ISO 8601 format.
2018-02-11T22:13:28.650328Z
Adjust into another time zone.
instant.atZone( // Apply a `ZoneId` to `Instant` object to get a `ZonedDateTime` object.
ZoneId.of( "Pacific/Auckland" )
).toString()
2018-02-12T11:13:28.650328+13:00[Pacific/Auckland]
Or capture current moment directly into that zone.
ZonedDateTime.now( // Capture current moment as seen on the wall-clock time of the people in a particular region.
ZoneId.of( "Pacific/Auckland" )
).toString() // Generate string in standard ISO 8601 format, wisely extended by appending the name of the time zone in square brackets.
2018-02-12T11:13:28.650328+13:00[Pacific/Auckland]
Details
The Answer by Grodriguez is correct but outdated.
java.time
The modern approach uses the java.time classes that supplant the troublesome old legacy date-time classes.
Your input string complies with the ISO 8601 formatting standard. The java.time classes use these formats by default when parsing/generating strings. So no need to specify a formatting pattern.
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).
Capture the current moment in UTC.
Instant instant = Instant.now() ; // Current moment in UTC.
To view that same simultaneous moment through the lens of a wall-clock time used by the people of another region (time zone), apply a ZoneId to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Note that we are working with smart objects here, not dumb strings. Do not conflate the date-time objects with mere strings that may represent their values textually.
If you want to generate a String in standard ISO 8601 format, call the toString method.
String outputA = instant.toString() ;
String outputB = zdt.toString() ;
To generate strings in other formats, use the DateTimeFormatter or DateTimeFormatterBuilder classes. Both are covered extensively on Stack Overflow, so search for more info.
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.
With a JDBC driver complying with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings or java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java 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 Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
I am working on a project that fetches Date/Time from backend in IST(Indian standard Time) as shown "2013-01-09T19:32:49.103+05:30". However when i parse it using following DateFormat
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
followed by parsing..
Date date = sdf.parse("2013-01-09T19:32:49.103+05:30");
System.out.println("XYZ ==============>"+date);
its Displaying date in GMT format as output i.e
Wed Jan 09 14:02:49 GMT+00:00 2013.
I have tried it using TimeZone class as..
TimeZone timeZone=TimeZone.getTimeZone("IST");
sdf.setTimeZone(timeZone);
but no effect..
How could i get a Date class Object having Date in IST format instead of GMT...
Please provide an appropriate solution..
EDIT:
This is how Code Looks Like:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
TimeZone timeZone=TimeZone.getTimeZone("IST");
sdf.setTimeZone(timeZone);
Date date = sdf.parse("2013-01-09T19:32:49.103+05:30");
String formattedDate=sdf.format(date);
System.out.println("XYZ ==============>"+formattedDate);
Date does not have any time zone. It is just a holder of the number of milliseconds since January 1, 1970, 00:00:00 GMT. Take the same DateFormat that you used for parsing, set IST timezone and format your date as in the following example
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date date = sdf.parse("2013-01-09T19:32:49.103+05:30");
sdf.setTimeZone(TimeZone.getTimeZone("IST"));
System.out.println(sdf.format(date));
output
2013-01-09T19:32:49.103+05:30
Note that XXX pattern is used for ISO 8601 time zone (-08:00) since 1.7. If you are in 1.6 try Z. See SimpleDateFormat API for details of format patterns
How could i get a Date class Object having Date in IST format instead of GMT...
You can't. Date doesn't have a format or a time zone. It simply represents a number of milliseconds since the Unix epoch of midnight on January 1st 1970 UTC. Instead, Date.toString() always uses the default time zone.
To use a specific format and time zone, use DateFormat instead of Date.toString(). You can set the time zone with DateFormat.setTimeZone() and then convert a Date to a String using DateFormat.format(). DateFormat itself has some factory methods for creation, or you can use SimpleDateFormat if you want to specify a particular pattern.
As Abu says, Joda Time is a much better date/time API than the built-in one, although for just formatting a date/time the standard library doesn't do a bad job. Just note that DateFormat and its subclasses are generally not thread-safe.
tl;dr
OffsetDateTime.parse( "2013-01-09T19:32:49.103+05:30" ) // Parsed.
.toInstant() // Adjusted to UTC.
See live code in IdeOne.com.
ISO 8601
Your input string of 2013-01-09T19:32:49.103+05:30 happen to be in standard ISO 8601 format. The +05:30 at the end indicates an offset-from-UTC of five and a half hours ahead, used in India.
java.time
You are using troublesome old date-time classes, now legacy, supplanted by the java.time classes.
The java.time classes happen to use ISO 8601 formats by default when parsing/generating Strings representing date-time values. So no need to specify a formatting pattern at all.
As your input represents a moment on the timeline with an offset-from-UTC, we parse as a OffsetDateTime object.
OffsetDateTime odt = OffsetDateTime.parse( "2013-01-09T19:32:49.103+05:30" );
odt.toString(): 2013-01-09T19:32:49.103+05:30
To obtain a simple object in UTC value, extract an Instant. This Instant class is a basic building-block class of java.time. 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 think of OffsetDateTime as an Instant plus a ZoneOffset.
Instant instant = odt.toInstant(); // UTC.
When calling toString, a String object is generated in standard ISO 8601 format. The Z on the end is short for Zulu and means UTC.
instant.toString(): 2013-01-09T14:02:49.103Z
An Instant is limited in various ways such as when generating Strings in various formats. So you may want to work with an OffsetDateTime adjusted into UTC as its offset; an offset-of-zero, in other words. The ZoneOffset class holds a constant for UTC, ZoneOffset.UTC.
OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC );
You can also apply an offset (or time zone) to an Instant. Call atOffset or atZone.
The Instant class is the basic building-block class of java.time. Likely to be used often in your code as best practice is to do most of your work in UTC.
OffsetDateTime odt = instant.atOffset( ZoneOffset.ofHoursMinutes( 5 , 30 ) );
Time zone
Note that an offset-from-UTC is not a time zone. A time zone is an offset plus a set of rules, past and present, for handling anomalies such as Daylight Saving Time (DST). So a time zone is always preferable to a mere offset if you are indeed sure of the correct zone.
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(!).
If you know the intended time zone, apply a ZoneId to get a ZonedDateTime object. But never assume without verifying with the source of your input data. Many different zones may share a particular offset. For example, in the case of our input here, the offset +05:30 happens to be used today in both India (Asia/Kolkata) and Sri Lanka (Asia/Colombo). Those two time zones may have different rules for different anomalies in their past, present, or future.
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
The toString method of ZonedDateTime extends standard ISO 8601 format in a wise way by appending the name of the time zone is square brackets. In this case, [Asia/Kolkata].
zdt.toString(): 2013-01-09T19:32:49.103+05:30[Asia/Kolkata]
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 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.
You can do this simply by use of Calender class. Please check below snippets:
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
calendar.setTimeInMillis(<--time stamp-->);
//calendar.setTime(<--date object of gmt date-->);
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy 'at' hh:mm a");
sdf.setTimeZone(TimeZone.getDefault());
String result=sdf.format(calendar.getTime());
I want to parse a date, which was created with a specific timezone, convert it to a format and return it. The conversion works but the timezone offset is always set to +0000 with the time difference being added/subtracted as necessary. How can I get it to format and keep the offset correct?
I expect this: 2012-11-30T12:08:56.23+07:00
But get this: 2012-11-30T05:08:56.23+00:00
Implementation:
public static final String ISO_8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSZZ";
public static String formatDateToISO8601Standard(Date date) {
DateTime dateTime = new DateTime(date);
DateTimeFormatter df = DateTimeFormat.forPattern(ISO_8601_DATE_FORMAT);
return dateTime.toString(df);
}
Test class:
private static final String DATE_WITH_TIMEZONE = "30 11 2012 12:08:56.235 +0700";
private static final String EXPECTED_DATE_WITH_TIMEZONE = "2012-11-30T12:08:56.23+07:00";
#Test public void testFormattingDateWithSpecificTimezone() throws Exception {
String result = JodaDateUtil.formatDateToISO8601Standard(createDate(DATE_WITH_TIMEZONE));
assertEquals("The date was not converted correctly", EXPECTED_DATE_WITH_TIMEZONE, result); }
private Date createDate(String dateToParse) throws ParseException {
DateTimeFormatter df = DateTimeFormat.forPattern("dd MM yyyy HH:mm:ss.SSS Z");
DateTime temp = df.parseDateTime(dateToParse);
Date date = temp.toDate();
return date; }
Basically, once you parse the date string [in your createDate() method] you've lost the original zone. Joda-Time will allow you to format the date using any zone, but you'll need to retain the original zone.
In your createDate() method, the DateTimeFormatter "df" can return the zone that was on the string. You'll need to use the withOffsetParsed() method. Then, when you have your DateTime, call getZone(). If you save this zone somewhere or somehow pass it to your formatting routine, then you can use it there by creating a DateTimeFormatter "withZone" and specifying that zone as the one you want on the format.
As a demo, here's some sample code in a single method. Hopefully, it'll help change your code the way you want it to run.
public static void testDate()
{
DateTimeFormatter df = DateTimeFormat.forPattern("dd MM yyyy HH:mm:ss.SSS Z");
DateTime temp = df.withOffsetParsed().parseDateTime("30 11 2012 12:08:56.235 +0700");
DateTimeZone theZone = temp.getZone();
Date date = temp.toDate();
DateTime dateTime = new DateTime(date);
DateTimeFormatter df2 = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSZZ");
DateTimeFormatter df3 = df2.withZone(theZone);
System.out.println(dateTime.toString(df2));
System.out.println(dateTime.toString(df3));
}
tl;dr
OffsetDateTime.parse (
"30 11 2012 12:08:56.235 +0700" ,
DateTimeFormatter.ofPattern ( "dd MM uuuu HH:mm:ss.SSS X" , Locale.US )
).toString()
2012-11-30T12:08:56.235+07:00
Details
The accepted Answer is correct. As soon as you convert to a java.util.Date object, you lose time zone information. This is complicated by the fact that java.util.Date::toString confusingly applies a current default time zone when generating the String.
Avoid using these old date-time classes like java.util.Date. They are poorly-designed, confusing, and troublesome. Now legacy, supplanted by the java.time project. So too is the Joda-Time project now supplanted by the java.time classes.
java.time
Parse that input string as a OffsetDateTime object as it includes an offset-from-UTC but lacks a time zone. Call DateTimeFormatter.ofPattern to specify a custom format matching your input string. Pass that formatter object to OffsetDateTime.parse.
String input = "30 11 2012 12:08:56.235 +0700" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "dd MM uuuu HH:mm:ss.SSS X" , Locale.US );
OffsetDateTime odt = OffsetDateTime.parse ( input , f );
odt:toString(): 2012-11-30T12:08:56.235+07:00
To see the same moment in UTC, extract an Instant. 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 = odt.toInstant();
instant.toString(): 2012-11-30T05:08:56.235Z
You can apply any time zone through which you want to view the same moment, the same point on the timeline.
ZonedDateTime zdtKolkata = odt.toInstant ().atZone ( ZoneId.of ( "Asia/Kolkata" ) );
zdtKolkata.toString(): 2012-11-30T10:38:56.235+05:30[Asia/Kolkata]
No need to mix in the old date-time classes at all. Stick with java.time. If you must use some old code not yet updated to java.time types, look to new methods added to the old classes to convert to/from java.time.
The equivalent of java.util.Date is Instant, both being a count-since-epoch of 1970-01-01T00:00:00Z in UTC. But beware of data-loss as the java.time classes support nanosecond resolution but the old classes are limited to milliseconds.
java.util.Date utilDate = java.util.Date.from( instant );
Live code
See live working code in 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, & 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.
Try this.
ISODateTimeFormat.dateTimeParser().parseDateTime(dateString),
then convert that to the format you desire.
Use the format
val formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSSZZ")
I need to convert a String containing date into an date object. The String will be of the format "yyyy-mm-dd HH:mm:ss.SSSSSS" and I want the same format in an date object.
For instance I have a string "2012-07-10 14:58:00.000000", and I need the resultant date object to be of the same format.
I have tried the below methods but, the resultant is not as expected.
java.util.Date temp = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss.SSSSSS").parse("2012-07-10 14:58:00.000000");
DateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
Date thisDate = dateFormat.parse("2012-07-10 14:58:00.000000");
The result is "Tue Jan 10 14:58:00 EST 2012". Please let me know where I am going wrong.
Thanks,
Yeshwanth Kota
java.util.Date temp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").parse("2012-07-10 14:58:00.000000");
The mm is minutes you want MM
CODE
public class Test {
public static void main(String[] args) throws ParseException {
java.util.Date temp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS")
.parse("2012-07-10 14:58:00.000000");
System.out.println(temp);
}
}
Prints:
Tue Jul 10 14:58:00 EDT 2012
For future reference:
yyyy => 4 digit year
MM => 2 digit month (you must type MM in ALL CAPS)
dd => 2 digit "day of the month"
HH => 2-digit "hour in day" (0 to 23)
mm => 2-digit minute (you must type mm in lowercase)
ss => 2-digit seconds
SSS => milliseconds
So "yyyy-MM-dd HH:mm:ss" returns "2018-01-05 09:49:32"
But "MMM dd, yyyy hh:mm a" returns "Jan 05, 2018 09:49 am"
The so-called examples at https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html show only output. They do not tell you what formats to use!
tl;dr
LocalDateTime.parse(
"2012-07-10 14:58:00.000000".replace( " " , "T" )
)
Microseconds do not fit
You are attempting to squeeze a value with microseconds (six decimal digits) into a data type capable only of milliseconds resolution (three decimal digits). That is impossible.
Instead, use a data type with fine enough resolution. The java.time classes use nanosecond resolution (nine decimal digits).
Unzoned input does not fit a zoned type
You are attempting to put a value lacking any offset-from-UTC or time zone into a data type (Date) that only represents values in UTC. So you are adding information (UTC offset) not intended by the input.
Use an appropriate data type instead. Specifically, java.time.LocalDateTime.
Case-sensitive
Other Answers and Comments correctly explain that the formatting pattern codes are case-sensitive. So MM and mm have different effects.
Avoid legacy classes
The troublesome old date-time classes bundled with the earliest versions of Java are now legacy, supplanted by the java.time classes built into Java 8 and later.
ISO 8601
Your input strings nearly comply with the ISO 8601 standard formats. Replace the SPACE in the middle with a T to comply fully.
The java.time classes use the standard formats by default when parsing/generating strings. So no need to specify a formatting pattern.
Date-time objects have no "format"
and I need the resultant date object to be of the same format.
No, date-time objects do not have a "format". Do not conflate date-time objects with mere strings. Strings are inputs and outputs of the objects. The objects maintain their own internal representions of the date-time info, the details of which are irrelevant to us as calling programmers.
java.time
Your input lacks any indicator of offset-from-UTC or troublesome me zone. So we parse as a LocalDateTime objects which lacks those concepts.
String input = "2012-07-10 14:58:00.000000".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
Generating strings
To generate a String representing the value of your LocalDateTime:
Call toString to get a String in standard ISO 8601 format.
Use DateTimeFormatter for producing strings in either custom formats or automatically-localized formats.
Search Stack Overflow for more info as these topics have been covered many many times already.
ZonedDateTime
A LocalDateTime does not represent an exact point on the timeline.
To determine an actual moment, assign a time zone. For example noon in Kolkata India comes much earlier than noon in Paris France. Noon without a time zone could be happening at any point over a range of about 26-27 hours.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
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.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 brought some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android (26+) bundle implementations of the java.time classes.
For earlier Android (<26), the process of API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
Your not applying Date formator. rather you are just parsing the date. to get output in this format
yyyy-MM-dd HH:mm:ss.SSSSSS
we have to use format() method here is full example:-
Here is full example:-
it will take Date in this format yyyy-MM-dd HH:mm:ss.SSSSSS
and as result we will get output as same as this format yyyy-MM-dd HH:mm:ss.SSSSSS
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
//TODO OutPut should LIKE in this format yyyy-MM-dd HH:mm:ss.SSSSSS.
public class TestDateExample {
public static void main(String args[]) throws ParseException {
SimpleDateFormat changeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS");
java.util.Date temp = changeFormat.parse("2012-07-10 14:58:00.000000");
Date thisDate = changeFormat.parse("2012-07-10 14:58:00.000000");
System.out.println(thisDate);
System.out.println("----------------------------");
System.out.println("After applying formating :");
String strDateOutput = changeFormat.format(temp);
System.out.println(strDateOutput);
}
}
its work for me
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.format(new Date));