This question already has answers here:
Parsing ISO-8601 DateTime with offset with colon in Java
(4 answers)
String date into Epoch time
(4 answers)
Closed 3 years ago.
I have this format:
2011-10-10T01:45:20+00:00
I tried using LocalDateTime.parse("2011-10-10T01:45:20+00:00")
but I got error:
java.time.format.DateTimeParseEception: Text '2011-10-10T01:45:20+00:00' could not be parse, unparsed text found
The default formatter is DateTimeFormatter.ISO_LOCAL_DATE_TIME : '2011-12-03T10:15:30', the offset is not in,
You may parse using OffsetDateTime class that uses DateTimeFormatter.ISO_OFFSET_DATE_TIME : '2011-12-03T10:15:30+01:00' as formatter
OffsetDateTime.parse("2011-10-10T01:45:20+00:00") // print 2011-10-10T01:45:20Z
You can still use LocalDateTime but you need to specify the formatter
LocalDateTime.parse("2011-10-10T01:45:20+00:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME); // 2011-10-10T01:45:20
Oracle Documentation
tl;dr
OffsetDateTime.parse( "2011-10-10T01:45:20+00:00" )
Wrong class
The LocalDateTime class is not appropriate to your input. That class represents only a date and a time-of-day but without any offset-from-UTC or time zone, so it does not represent a moment, is not a point on the timeline.
Your input string in contrast represents a moment, with an offset-from-UTC of zero hours-minutes-seconds: +00:00
OffsetDateTime
Correct class for your input is OffsetDateTime.
Your input string is in standard ISO 8601 format. These standard formats are used by default in the java.time classes. So no need to specify a formatting pattern.
OffsetDateTime odt = OffsetDateTime.parse( "2011-10-10T01:45:20+00:00" ) ;
See this code run live at IdeOne.com.
odt.toString(): 2011-10-10T01:45:20Z
FYI, the difference between offset and zone:
An offset-from-UTC is merely a number of hours-minutes-seconds. Nothing more. Represented by ZoneOffset class.
A time zone is much more. A time zone is a history of past, present, and future changes to the offset used by the people of a particular region. A time zone carries a name in Continent/Region format such as America/Montreal or Africa/Tunis. Represented by ZoneId class.
You could provide ISO date formatter in the parse method like this
import java.time.format.DateTimeFormatter
LocalDate.parse("2011-10-10T01:45:20+00:00", DateTimeFormatter.ISO_DATE_TIME)
Related
I am trying to convert the value 2022-04-30 14:34:52.900426+00:00 an instance of LocalDateTime. I have written the following code:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS'Z'");
I am getting the following error
could not be parsed at index 26
What should my formatter string be?
tl;dr
OffsetDateTime // Use `OffsetDateTime`, not `LocalDateTime`, to represent a date with time and offset.
.parse(
"2022-04-30 14:34:52.900426+00:00" // Almost in ISO 8601 format.
.replace( " " , "T" ) // Replace SPACE with T to comply with ISO 8691.
)
See this code run live at IdeOne.com.
Wrong class, use OffsetDateTime, not LocalDateTime
LocalDateTime is exactly the wing class to use in this case. That represents a date with time-of-day. But your input indicates a date with time-of-day and an offset-from-UTC. The +00:00 means an offset of zero hours-minutes-seconds from UTC.
So parse that input as a OffsetDateTime object instead.
Rather than define a formatting pattern, I suggest merely replacing the SPACE in the middle with a T to comply with the ISO 8601 standard used by default in the java.time classes when parsing/generating text.
String input = "2022-04-30 14:34:52.900426+00:00".replace( " " , "T" ) ;
OffsetDateTime odt = OffsetDateTime.parse( input ) ;
It's not working because the UTC Time offsets hasn't been written properly. It should look like this with a custom DateTimeFormatter:
//Custom DatTimeFormatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSZZZZZ");
formatter.parse("2022-04-30 14:34:52.900426+00:00");
You could either use the predefined ISO_OFFSET_DATE_TIME DatTimeFormatter only by replacing the space between date and time with a capital T, as the standard requires.
//Predefined DateTimeFormatter
DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse("2022-04-30T14:34:52.900426+00:00");
Besides, to answer your question under #Taco Jan Osinga's reply:
No, it is not correct to use "+00:00" to just match the datetime you're trying to parse. That custom DateTimeFormatter you would build would only match datetime referring to your local TimeZone; thus it won't work with datetime from different areas.
Have you tried "yyyy-MM-dd HH:mm:ss.SSSSSS+00:00"?
I've tried all sorts of different conversions with different Java formatters but I'm still not having any luck with something that seems simple.
I have a string that is a date/time in UTC. I'm trying to convert that to another time zone. Is any one able to tell me why the below isn't working? The time zone is changing but it's not changing the right way.
Updated: (though it doesn't seem like I'm setting the time zone to UTC properly as the conversion isn't correct either).
String dateInput = "2021-02-16 20:57:43";
SimpleDateFormat mdyUtc = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
mdyUtc.setTimeZone(TimeZone.getTimeZone("UTC");
Date utcOutput = mdyUtc.parse(dateInput);
SimpleDateFormat mdyOffset = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
mdyOffset.setTimeZone(TimeZone.getTimeZone("GMT-10:00");
Date localOutput = mdyOffset.parse(dateInput);
System.out.print("UTC date = " + utcOutput);
System.out.print("Changed date = " + localOutput);
Output:
UTC date = Tue Feb 16 15:57:43 EST 2021
Changed date = Wed Feb 17 01:57:43 EST 2021
java.time
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*.
Using the modern date-time API:
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 dateInput = "2021-02-16 20:57:43";
// Replace ZoneId.systemDefault() with ZoneOffset.UTC if this date-time is in UTC
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH)
.withZone(ZoneId.systemDefault());
ZonedDateTime zdt = ZonedDateTime.parse(dateInput, dtf);
ZonedDateTime result = zdt.withZoneSameInstant(ZoneId.of("GMT-10:00"));
System.out.println(result);
}
}
Output:
2021-02-16T10:57:43-10:00[GMT-10:00]
ONLINE DEMO
Learn more about the modern date-time API from Trail: Date Time.
Can I get java.util.Date from ZonedDateTime?
If at all you need to use java.util.Date, you can convert ZonedDateTime into it as follows:
Date date = Date.from(result.toInstant());
Note that the 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). When you print an object of java.util.Date, its toString method returns the date-time in the JVM's timezone, calculated from this milliseconds value. If you need to print the date-time in a different timezone, you will need to set the timezone to SimpleDateFormat and obtain the formatted string from it.
* 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.
tl;dr
LocalDateTime // Represent a date with time-of-day but lacking the context of a time zone or offset-from-UTC.
.parse( // Interpret some text in order to build a date-time object.
"2021-02-16 20:57:43".replace( " " , "T" ) // Convert to standard ISO 8601 string to parse by default without needing to specify a formatting pattern.
) // Returns a `LocalDateTime` object.
.atOffset( // Place that date with time into the context of an offset. Determines a moment, a specific point on the timeline.
ZoneOffset.UTC // A constant for an offset of zero hours-minutes-seconds.
) // Returns an `OffsetDateTime` object.
.atZoneSameInstant( // Adjust the view of this moment as seen in the wall-clock time of some other time zone. Still the same moment, same point on the timeline.
ZoneId.of( "Pacific/Honolulu" ) // Use a time zone, if known, rather than a mere offset.
) // Returns a `ZonedDateTime` object.
.toString() // Generate text representing this moment in standard ISO 8601 format extended to append the time zone name in square brackets.
See this code run live at IdeOne.com.
2021-02-16T10:57:43-10:00[Pacific/Honolulu]
Details
The Answer by Avinash is correct, using a DateTimeFormatter with an assigned ZoneId. That works, but I prefer keeping the zone assignment separate from the formatter, to be more explicit to someone reading the code. This is only about my preference, not about correctness; both Answers are equally correct.
Parse your input as a LocalDateTime, as the input represents a date with time-of-day but lacks any indication of offset or time zone.
By default, the java.time classes use standard text formats defined in ISO 8601. If an input complies, no need to specify a formatting pattern. To comply, replace your input’s SPACE character in the middle with a T.
String input = "2021-02-16 20:57:43".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
You said you know for certain that input was meant to represent a date with time as seen in UTC, having an offset-from-UTC of zero hours-minutes-seconds. So we can apply an offset of zero using ZoneOffset to produce a OffsetDateTime.
Also, I suggest you educate the publisher of your data feed about using ISO 8601 formats to communicate that offset-of-zero fact by appending a Z (as well as using T in the middle).
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ; // Place date with time into context of an offset of zero.
Lastly, you said you want to adjust that moment to another time zone. Apply a ZoneId to get a ZonedDateTime object.
Actually, you specified an offset of "GMT-10:00". But it is better to use a time zone if known rather than a mere offset. A time zone is a history of past, present, and future changes to the offset used by the people of a particular region.
I will guess you want Hawaii time, Pacific/Honolulu.
ZoneId z = ZoneId.of( "Pacific/Honolulu" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
The java.util.Date API is deprecated; you should look into the new Date and Time APIs around LocalTime et al.
That said, if you want to keep the old code: It is a bit brittle. Your initial date input does not specify a time zone, so you'll probably get the system's time zone. You should specify a time zone --- if the expected input is UTC, say so.
Then you need to specify the time zone either in an hour offset or with a name, not both.
When I change your code to use
mdyOffset.setTimeZone(TimeZone.getTimeZone("-10:00"));
I get
Changed date = Tue Feb 16 14:57:43 CST 2021
which seems to fit, as I'm on CST (currently 6 hours after GMT), so 20:57:43 minus 6 is 14:57:43. Again, this is displayed in my local time zone. You may have to use a DateFormat to adjust the output as needed.
By means of classes like SimpleDateFormat it is possible to format time and date in a suitable format.
Examples here
https://developer.android.com/reference/java/text/SimpleDateFormat#examples
In Java it starts with milliseconds value and then that value gets translated into human readable format.
Sometime it is useful to have that value instead of the human readable form.
Example:
If I am not wrong the 1578738100000 value just means the UTC value Sat Jan 11 2020 10:21:40.
Is it possible to have a format string that yields a string with milliseconds instead of the human readable form?
I know that it is possible to get the milliseconds value directly from the Date class but what I am asking here is whether milliseconds are one of the possible format string to feed SimpleDateFormat (or similar classes) with.
Be clear in understanding that date-time value objects and formatter objects play different roles.
A date-time object has no format, it represents a date and/or time-of-day with or without the context of a time zone or offset-from-UTC.
A formatter has no value, no date nor time-of-day. A formatter’s job is to work with a date-time object to produce text in a certain format representing that date-time object’s value.
So tracking a count of milliseconds since the epoch reference is the job of the date-time object, not the formatter. Producing human-readable text is the job of the formatter. So, no, the formatter does not produce a count of milliseconds.
And, no, you should not be using a count of milliseconds to communicate date-time values. Such numbers have no meaning to a human reader which leads to easily missing erroneous data. And such data does not readily identify itself - is it a number of whole seconds, milliseconds, microseconds, or nanoseconds? And what is the epoch reference date, which of the couple dozen commonly used epochs?
Instead communicate date-time values as text using the ISO 8601 standard formats.
Another problem: you are using terrible date-time classes that were supplanted years ago by the modern java.time classes defined in JSR 310.
If your number is a count of milliseconds since the epoch reference of first moment of 1970 in UTC, parse as a Instant.
Instant instant = Instant.ofEpochMilli( 1_578_738_100_000L ) ;
If you insist on working with a count-from-epoch against my advice, you can interrogate the Instant.
long milliseconds = instant.toEpochMilli() ;
Generate text in standard ISO 8601 format.
String output = instant.toString() ;
For other formats, adjust the Instant into an OffsetDateTime or ZonedDateTime object, and generate text with a DateTimeFormatter. All this has been covered many many times already. So search Stack Overflow to learn more.
instant
.atZone(
ZoneId.of( "America/Montreal" )
)
.format(
DateTimeFormatter
.ofLocalizedDateTime( FormatStyle.FULL )
.withLocale( Locale.CANADA_FRENCH )
)
Lastly, be aware that while the legacy classes were limited to a resolution of milliseconds, the java.time classes revolve to the much finer nanoseconds. So beware of possible data loss when calling Instant::toEpochMilli as any microseconds or nanoseconds are ignored,
The old and outdated SimpleDateFormat class cannot do that. Its replacement, the modern DateTimeFormatter, can.
DateTimeFormatter epochMilliFormatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.INSTANT_SECONDS)
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
.toFormatter();
Instant sampleInstant = OffsetDateTime
.of(2020, 1, 11, 10, 21, 40, 0, ZoneOffset.UTC)
.toInstant();
String formattedValue = epochMilliFormatter.format(sampleInstant);
System.out.println(formattedValue);
Output from this snippet is the number you mentioned:
1578738100000
Using ChronoField.INSTANT_SECONDS in the formatter gives us the seconds since the epoch. We wanted milliseconds, so we need to append ChronoField.MILLI_OF_SECOND immediately and make sure that they are printed in exact 3 positions, zero padded. This is what the 3 as 2nd argument to appendValue() does.
Is it possible to have a format string that yields a string with
milliseconds …?
No, with a format pattern string it is not possible, neither with SimpleDateFormat nor with DateTimeFormatter. You can go through the possible pattern letter of each and see that there is no pattern letter for neither seconds nor milliseconds since the epoch.
Are you sure that you want it, though? Even if this is for storing or for data interchange between systems, using milliseoncds since the epoch is not generally recommended exactly because they not human readable and therefore troublesome in debugging and in ad hoc queries. For most purposes you will be better off using a string in ISO 8601 format, like 2020-01-11T10:21:40Z. See the other answer by Basil Bourque for details. ISO 8601 format has been designed to be readable by both humans and computers.
You should not have wanted to use SimpleDateFormat anyway
The SimpleDateFormat class is notoriously troublesome (though even more for parsing than for formatting). It is also long outdated. The Date class that you mentioned is poorly designed and long outdated too. I recommend that you use java.time, the modern Java date and time API, as I do above.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Documentation of DateTimeFormatter with the format pattern letters that it accepts.
Wikipedia article: ISO 8601
This question already has answers here:
Change date format in a Java string
(22 answers)
want current date and time in "dd/MM/yyyy HH:mm:ss.SS" format
(11 answers)
How to convert date in to yyyy-MM-dd Format?
(6 answers)
display Java.util.Date in a specific format
(11 answers)
Closed 3 years ago.
I know that this question that I am asking has answer all over the net but I want the yyyy-MM-dd format in Date type as SimpleDateFormat.format("yyyy-MM-dd") returns the string value and also I have tried SimpleDateFormat.parse("yyyy-MM-dd") but it does not provide the value in required format. Could anyone help how to get "yyyy-MM-dd" format in Date type variable. Example what I am trying to do is shown below-
Date date = new Date(); // this will give the outpur something like this Thu 28 Nov....
But I want the output in this format 2019-11-28 where date variable should not change its type.
tl;dr
Capture the current date, using java.time.LocalDate.
LocalDate // Represent a date-only value, without time-of-day and without time zone.
.now( // Capture the current date. Time zone required, as the date is not the same around the globe.
ZoneId.of( "Pacific/Auckland" )
) // Returns a `LocalDate` object.
.toString() // Generates a `String` object whose text is in standard ISO 8601 format: YYYY-MM-DD
2020-01-23
Perhaps you are being handed a java.util.Date object by old code not yet updated to java.time classes. Convert from a given java.util.Date object (legacy) to Instant & ZonedDateTime (modern).
myJavaUtilDate // `java.util.Date` is one of the terrible date-time classes, now legacy.
.toInstant() // Convert to the modern `java.time.Instant` class that replaces `Date`.
.atZone( // Adjust from UTC to the time zone through which you want to perceive the date.
ZoneId.of( "Asia/Tokyo" ) // Specify a proper time zone in `Continent/Region` format, never 2-4 letter pseudo-zone such as PDT, CST, IST, and such.
) // Returns a `ZonedDateTime` object.
.format( // Generate text representing the value within our `ZonedDateTime` object.
DateTimeFormatter.ISO_LOCAL_DATE // Specify a formatter. Here, the standard ISO 8601 formatter for date-only value: YYYY-MM-DD.
) // Returns a `String`.
2020-01-23
java.time
You are using terrible date-time classes that were supplanted years ago by the java.time classes defined in JSR 310.
LocalDate
If you just want the current date, use LocalDate.now.
LocaleDate.now( ZoneId.of( "Europe/Berlin" ) ).toString() // Yields something like '2020-01-23'.
Instant
Convert java.util.Date to its replacement, java.time.Instant. Both represent a moment in UTC, though the modern class has a fiber resolution of nanoseconds versus milliseconds.
To convert, use new to/from methods added to the old classes.
Instant instant = myJavaUtilDate.toInstant() ;
ZonedDateTime
For any given moment, the date varies around the globe by time zone. A few minutes after midnight in Paris France is a new day, while still “yesterday” in Montréal Québec.
So determining a date requires a time zone.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Text
Could anyone help how to get "yyyy-MM-dd" format in Date type variable.
Text has a “format”, but date-time objects do not. Date-time objects can be instantiated by parsing text. Date-time objects can generate text to represent t the value held internally. But the date-time object and the String object are separate and distinct.
Generate text for the date only, without the time of day and without the time zone appearing.
String output = zdt.format( DateTimeFormatter.ISO_LOCAL_DATE ) ;
Convert it to java.sql.Date :
Date obj = new Date();
java.sql.Date sqlDate = new java.sql.Date(obj.getTime());
System.out.println(sqlDate);
Try this one:
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
String strDate= formatter.format(date);
System.out.println(strDate);
or check this site: https://www.javatpoint.com/java-simpledateformat
I don't think that you can change the format of a Date object itself, therefore you should use DateFormatters, like mentioned above the SimpleDateFormat.
Also, you maybe should consider using LocalDate/LocalDateTime or Instant instead of Date.
I have the following date value 1995-12-31T23:59:59
but in order to parse this for a solr query I need it in the below format
1995-12-31T23:59:59Z
How can I parse this to get the added "Z" on the end in java 1.6 ?
The type must be java.util.date after the conversion - fyi
When I toString the date now and attempt to parse it with the SimpleDateFormat object it looks like this
"Mon Jan 01 00:00:00 CST 2001" - what is this format to convert it?
Use SimpleDateFormat:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Date d = df.parse("1995-12-31T23:59:59Z");
System.out.println(d);
Put the 'Z' in single quotes to escape
"Z" is the time zone abbreviation for Zulu time zone i.e. UTC. If solr API accepts the date object, then you can just parse the date in the following way by setting preferred timezone:
SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateParser.setTimeZone(TimeZone.getTimeZone("Z"));
Date date = df.parse("1995-12-31T23:59:59");
If you need to convert it back to string then use the method provided by nsfyn55:
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
System.out.println(dateFormatter.format());
Avoid Old Date-Time Classes
You are using the old java.util.Date/.Calendar and SimpleDateFormat classes. Avoid them.
The Date class has the poor design choice of its toString applying a default time zone when generating a String. So it seems like it has a time zone when in fact it does not (except one buried underneath that is ignored for regular use). Confusing, yes. Avoid it.
java.time
Instead use java.time built into Java 8 and later.
First parse as a LocalDateTime without any time zone or offset.
LocalDateTime ldt = LocalDateTime.parse( "1995-12-31T23:59:59Z" );
Apply a time zone or offset-from-UTC to give this LocalDateTime meaning, to make it an actual moment on the timeline. You have to know, or ask, what time zone or offset was intended by this string as no indication was embedded. For this example, I will arbitrarily assume Québec.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );
Your desired output has a Z on the end, for Zulu which means UTC.
In java.time an Instant represents a moment on the timeline in UTC. You can extract an Instant from the ZonedDateTime.
Instant instant = zdt.toInstant();
The Instant class’ toString method generates a string in your desired format. That format is one of the standard ISO 8601 formats.
String output = instant.toString();
Half-Open
I happened to notice that your example value was trying to get the end of 1995. There is a better way to do such search or comparison criteria.
In date-time work, the best practice is called Half-Open where the beginning of a span of time is inclusive while the ending is exclusive. So a week starts on Monday and runs up to, but not including, the next Monday.
Defining a year means starting at the first moment of the first day of 1995 and running up to but not including the first moment of the first day of the following year, 1996. Searching for any values within that range is done not with a BETWEEN but as: ( someEvent >= firstMomentOf1995 AND someEvent < firstMomentOf1996 ) ( not <= ).