Cant parse recently formatted ZonedDateTime Java 8 - java

Why this code
DateTimeFormatter SENT_DATE_FORMATTER = DateTimeFormatter.ofPattern("E, d MMM YYYY HH:mm:ss Z", Locale.US);
ZonedDateTime now = ZonedDateTime.now();
String dateStr = now.format(SENT_DATE_FORMATTER);
System.out.println(dateStr);
ZonedDateTime zoned = ZonedDateTime.parse(dateStr, SENT_DATE_FORMATTER);
Prints the correct date on the sysout line but throws a DateTimeParseException (Unable to obtain ZonedDateTime from TemporalAccessor) on the parse line?

Capitalized Y stands for week-based-year, see javadoc. In order to make the parser working you rather need to change it to year (u) or year-of-era (y). Then the parser can create a date out of calendar year, month (M) and day-of-month (d). Keep in mind that the week-based-year can relate to previous or next calendar year, not the actual one if your month and day-of-month are near the start or end of calendar year. Therefore it is not possible to just equalize the week-based-year to the calendar year! And without a precisely defined calendar year it is not possible to form a date.
Otherwise, if you had the week-of-week-based-year (w) in your pattern, too, then your parser would be able to understand the input because week-based-year (Y), week-of-week-based-year (w) and day-of-week (E) would also make an interpretable combination for a date.
Note however, that all given details in the input matching your pattern must be consistent (for example 2015-08-31 is Monday and not Tuesday) otherwise the parser will complain again (at least in strict mode).

Related

Not able to understand "YYYY-MM-DDTHH:MM:SS" date format

I am trying to parse following date time string
2018-01-30T23:59:59.000
I am not able to understand which standard format it is like UTC or ISO_8601
while parsing in the following manner:
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD'T'HH:MM:SS:MS");
Date date = null;
try {
date = sdf.parse("2018-01-30T23:59:59.000");
} catch (ParseException e) {
e.printStackTrace();
}
But It is throwing following exception:
java.text.ParseException: Unparseable date: "2018-01-30T23:59:59.000"
Any help is appreciated.
See the doc of SimpleDateFormat and try this:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
LocalDateTime dateTime = LocalDateTime.parse("2018-01-30T23:59:59.000");
System.out.println(dateTime);
This prints:
2018-01-30T23:59:59
Your string is in ISO 8601 format. UTC or Coordinated Universal Time is not a format, it is a standard time used to define the time the rest of use in our respective time zones.
The date-time classes you were using, SimpleDateFormat and Date, are long outdated and the former in particular notoriously troublesome. I recommend that you instead use java.time, the modern Java date and time API. It is so much nicer to work with.
A LocalDateTime is a date with time of day and without time zone or offset from UTC. Its one-argument parse method parses ISO 8601, which is why no explicit formatter is needed.
What went wrong in your code
Your format pattern string has a number of issues to it. Which is one reason why you should appreciate the above solution without any explicit formatter. The first thing that goes wrong is: Your format pattern string has a colon, :, between seconds and milliseconds, whereas your date-time string has a dot, .. This is why you get the exception.
However, fixing this, your code yields the following Date:
Sun Dec 31 23:00:00 CET 2017
It’s one month off from the expected, and the minutes and seconds are missing. Because:
Uppercase YYYY is for week-based year and only useful with a week number. You need lowercase yyyy for year.
Uppercase DD is for day of year. You need lowercase dd for day of month.
You correctly used uppercase MM for month. Trying the same again for minutes won’t work. Maybe you can guess by now: it’s lowercase mm.
Not surprising you need lowercase ss for seconds.
UsingMS for milliseconds is interesting. SimpleDateFormat takes it as M for month (which we’ve already had twice before) and uppercase S for millisecond. Instead you needed uppercase SSS for the three digits of milliseconds.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
Wikipedia article: Coordinated Universal Time on UTC
You need to escape the literal T:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:SS");
See This SO Answer for more examples
Update: Your string is in the format
yyyy-MM-dd'T'HH:mm:ss.SSS
but you are trying to parse it with a completely uppercase format string.
This does not do what you want it to do and you should read the documentation on SimpleDateFormat and the format string placeholders

JodaTime allows invalid date

I expected this to throw an exception because the 1st of February 2016 is not a Friday:
final DateTimeFormatter formatter = DateTimeFormat.forPattern("EEEE, d MMMM yyyy");
final DateTime date = formatter.parseDateTime("Friday, 1 February 2016");
System.out.println(formatter.print(date));
Instead, it printed out Friday, 5 February 2016. What am I missing here?
It's explained in the doc (http://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormatter.html)
Parsing builds up the resultant instant by 'setting' the value of each parsed field from largest to smallest onto an initial instant, typically 1970-01-01T00:00Z. This design means that day-of-month is set before day-of-week. As such, if both the day-of-month and day-of-week are parsed, and the day-of-week is incorrect, then the day-of-week overrides the day-of-month. This has a side effect if the input is not consistent.

Conversion of a date to epoch Java [duplicate]

This question already has answers here:
SimpleDateFormat producing wrong date time when parsing "YYYY-MM-dd HH:mm"
(5 answers)
Closed 4 years ago.
I want to convert 2018-02-21 15:47:35 UTC to epoch UTC form. How do we do it? I am currently in PST.
SimpleDateFormat df = new SimpleDateFormat("YYYY-MM-DD HH:MM:SS");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
date = df.parse(dateString).getTime();
The code above should return the number of milliseconds since January 1, 1970, 00:00:00 GMT, but I'm getting an incorrect value.
The only problem with your code is DateFormat
please check.
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
String dateString = "2018-02-21 15:47:35";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = df.parse(dateString);
long time = date.getTime();
System.out.println(time);
System.out.println(new Date(time));
System.out.println(date);
I'm in PKT so output would differ...
1519228055000
Wed Feb 21 20:47:35 PKT 2018
Wed Feb 21 20:47:35 PKT 2018
Expected: 2018-02-21 15:47:35 UTC is equivalent to 1 519 228 055 000 milliseconds since the epoch of January 1, 1970 at 0:00 UTC.
Observed: Your code in the question gives 1 514 818 800 035. So it’s 4 409 254 965 milliseconds off, a little over 51 days.
The solution:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
date = LocalDateTime.parse("2018-02-21 15:47:35", dtf)
.atOffset(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
This gives the correct 1 519 228 055 000.
What went wrong?
One of the many troublesome traits of SimpleDateFormat is that with its default settings, if you specify an incorrect format pattern string, it will very often give you an incorrect result and pretend all is well. The modern Java date and time API that I am using in my snippet, is trying somewhat harder to figure out when the pattern doesn’t make sense and tell you it’s wrong somehow. As an example, let’s try your format pattern with the modern DateTimeFormatter:
final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-DD HH:MM:SS");
LocalDateTime.parse(dateString, dtf);
This will throw a java.time.format.DateTimeParseException: Text '2018-02-21 15:47:35' could not be parsed at index 14. Index 14 is where 47 is in the string, it was supposed to be the minutes. Apparently 47 doesn’t match MM in the format. If you haven’t figured out yet, check the documentation. It says that uppercase M is for “month-of-year”. So what the formatter is trying to tell you is there are not 47 months in a year. In the documentation you will also find lowercase m for “minute-of-hour”. As you correct the case of the letters in the format pattern string, you will receive other exceptions until you end up with either yyyy-MM-dd HH:mm:ss or uuuu-MM-dd HH:mm:ss (lowercase yyyy is year or era while uuuu is a signed year, both work for years after year 0).
Links
Oracle tutorial: Date Time explaining how to use java.time.
DateTimeFormatter documentation spelling out the uppercase and lowercase letters of format pattern strings.
Also can be done via java8 time library:
String dateString = "2018-02-21 15:47:35";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
dateTimeFormatter.withZone(ZoneId.of("UTC"));
LocalDateTime parsedDateTime = LocalDateTime.from(dateTimeFormatter.parse(dateString));
ZonedDateTime timeAtYourZone = parsedDateTime.atZone(ZoneId.systemDefault());
System.out.println(timeAtYourZone.toInstant().toEpochMilli());
System.out.println(timeAtYourZone);
Your pattern must be yyyy-MM-dd HH:mm:ss, as the other answers told you:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
I just want to add some more details.
First of all, take a look at the patterns description in the javadoc: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Note that a lowercase y is not the same as the uppercase Y (lowercase is the year, while uppercase is the week year - 2 different fields with completely different definitions)
Also note that uppercase D is the day of the year, while the day of the month (which is what you want) is the lowercase d. And uppercase M is the month, while lowercase m is the minute of hour.
And uppercase S is the milliseconds field, while the seconds are represented by lowercase s.
And SimpleDateFormat's design doesn't help: the class simply tries to parse the string, even if the month field (MM) appears twice in your pattern, while the minutes field doesn't appear (and it's set to a default value of zero - all behind the scenes, without any warning, no indication of error at all).
Conclusion: always read the docs :-)
For Java 8 or higher, consider using the new date API, which is much better because it doesn't have all these behind-the-scenes stuff:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneOffset.UTC);
long epochMilli = Instant.from(fmt.parse("2018-02-21 15:47:35")).toEpochMilli();
This API will also throw an exception if you use a pattern like YYYY-MM-DD HH:MM:SS, because it will try to parse the minutes value 47 as a month (because uppercase MM will be in the respective position), and 47 is not a valid month.

How to format time to 2 digit numbers? [duplicate]

Java 8 added a new java.time API for working with dates and times (JSR 310).
I have date and time as string (e.g., "2014-04-08 12:30"). How can I obtain a LocalDateTime instance from the given string?
After I finished working with the LocalDateTime object: How can I then convert the LocalDateTime instance back to a string with the same format as shown above?
Parsing date and time
To create a LocalDateTime object from a string you can use the static LocalDateTime.parse() method. It takes a string and a DateTimeFormatter as parameter. The DateTimeFormatter is used to specify the date/time pattern.
String str = "1986-04-08 12:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);
Formatting date and time
To create a formatted string out a LocalDateTime object you can use the format() method.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.of(1986, Month.APRIL, 8, 12, 30);
String formattedDateTime = dateTime.format(formatter); // "1986-04-08 12:30"
Note that there are some commonly used date/time formats predefined as constants in DateTimeFormatter. For example: Using DateTimeFormatter.ISO_DATE_TIME to format the LocalDateTime instance from above would result in the string "1986-04-08T12:30:00".
The parse() and format() methods are available for all date/time related objects (e.g. LocalDate or ZonedDateTime)
You can also use LocalDate.parse() or LocalDateTime.parse() on a String without providing it with a pattern, if the String is in ISO 8601 format.
For example,
String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
System.out.println("Date: " + aLD);
String strDatewithTime = "2015-08-04T10:11:30";
LocalDateTime aLDT = LocalDateTime.parse(strDatewithTime);
System.out.println("Date with Time: " + aLDT);
Output,
Date: 2015-08-04
Date with Time: 2015-08-04T10:11:30
And use DateTimeFormatter only if you have to deal with other date patterns.
For instance, in the following example, dd MMM uuuu represents the day of the month (two digits), three letters of the name of the month (Jan, Feb, Mar,...), and a four-digit year:
DateTimeFormatter dTF = DateTimeFormatter.ofPattern("dd MMM uuuu");
String anotherDate = "04 Aug 2015";
LocalDate lds = LocalDate.parse(anotherDate, dTF);
System.out.println(anotherDate + " parses to " + lds);
Output
04 Aug 2015 parses to 2015-08-04
also remember that the DateTimeFormatter object is bidirectional; it can both parse input and format output.
String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
DateTimeFormatter dTF = DateTimeFormatter.ofPattern("dd MMM uuuu");
System.out.println(aLD + " formats as " + dTF.format(aLD));
Output
2015-08-04 formats as 04 Aug 2015
(See complete list of Patterns for Formatting and Parsing DateFormatter.)
Symbol Meaning Presentation Examples
------ ------- ------------ -------
G era text AD; Anno Domini; A
u year year 2004; 04
y year-of-era year 2004; 04
D day-of-year number 189
M/L month-of-year number/text 7; 07; Jul; July; J
d day-of-month number 10
Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter
Y week-based-year year 1996; 96
w week-of-week-based-year number 27
W week-of-month number 4
E day-of-week text Tue; Tuesday; T
e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T
F week-of-month number 3
a am-pm-of-day text PM
h clock-hour-of-am-pm (1-12) number 12
K hour-of-am-pm (0-11) number 0
k clock-hour-of-am-pm (1-24) number 0
H hour-of-day (0-23) number 0
m minute-of-hour number 30
s second-of-minute number 55
S fraction-of-second fraction 978
A milli-of-day number 1234
n nano-of-second number 987654321
N nano-of-day number 1234000000
V time-zone ID zone-id America/Los_Angeles; Z; -08:30
z time-zone name zone-name Pacific Standard Time; PST
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z zone-offset offset-Z +0000; -0800; -08:00;
p pad next pad modifier 1
' escape for text delimiter
'' single quote literal '
[ optional section start
] optional section end
# reserved for future use
{ reserved for future use
} reserved for future use
Both Sufiyan Ghori's and micha's answer explain very well the question regarding string patterns. However, just in case you are working with ISO 8601, there isn't any need to apply DateTimeFormatter since LocalDateTime is already prepared for it:
Convert a LocalDateTime to a Time Zone ISO 8601 String
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneOffset.UTC); // You might use a different zone
String iso8601 = zdt.toString();
Convert from ISO8601 String back to a LocalDateTime
String iso8601 = "2016-02-14T18:32:04.150Z";
ZonedDateTime zdt = ZonedDateTime.parse(iso8601);
LocalDateTime ldt = zdt.toLocalDateTime();
Parsing a string with date and time into a particular point in time (Java calls it an "Instant") is quite complicated. Java has been tackling this in several iterations. The latest one, java.time and java.time.chrono, covers almost all needs (except time dilation :) ).
However, that complexity brings a lot of confusion.
The key to understand date parsing is:
Why does Java have so many ways to parse a date?
There are several systems to measure a time. For instance, the historical Japanese calendars were derived from the time ranges of the reign of the respective emperor or dynasty. Then there is, e.g., the Unix timestamp.
Fortunately, the whole (business) world managed to use the same.
Historically, the systems were being switched from/to, for various reasons. E.g., from the Julian calendar to the Gregorian calendar in 1582; so, the 'western' dates before that need to be treated differently.
And, of course, the change did not happen at once. Because the calendar came from the headquarters of some religion and other parts of Europe believed in other deities, for instance Germany did not switch until the year 1700.
...and why is the LocalDateTime, ZonedDateTime et al. so complicated
There are time zones.
A time zone is basically a "stripe"*[3] of the Earth's surface whose authorities follow the same rules of when does it have which time offset. This includes summer time rules.
The time zones change over time for various areas, mostly based on who conquers whom. And one time zone's rules change over time as well.
There are time offsets. That is not the same as time zones, because a time zone may be, e.g., "Prague", but that has summer time offset and winter time offset.
If you get a timestamp with a time zone, the offset may vary, depending on what part of the year it is in. During the leap hour, the timestamp may mean two different times, so without additional information, it can't be reliably converted.
Note: By timestamp I mean "a string that contains a date and/or time, optionally with a time zone and/or time offset."
Several time zones may share the same time offset for certain periods. For instance, the GMT/UTC time zone is the same as the "London" time zone when the summer time offset is not in effect.
To make it a bit more complicated (but that's not too important for your use case):
The scientists observe Earth's dynamic, which changes over time; based on that, they add seconds at the end of individual years. (So 2040-12-31 24:00:00 may be a valid date-time.) This needs regular updates of the metadata that systems use to have the date conversions right. E.g., on Linux, you get regular updates to the Java packages including these new data.
The updates do not always keep the previous behavior for both historical and future timestamps. So it may happen that parsing of the two timestamps around some time zone's change comparing them may give different results when running on different versions of the software. That also applies to comparing between the affected time zone and other time zone.
Should this cause a bug in your software, consider using some timestamp that does not have such complicated rules, like Unix timestamp.
Because of 7, for the future dates, we can't convert dates exactly with certainty. So, for instance, current parsing of 8524-02-17 12:00:00 may be off a couple of seconds from the future parsing.
JDK's APIs for this evolved with the contemporary needs
The early Java releases had just java.util.Date which had a bit naive approach, assuming that there's just the year, month, day, and time. This quickly did not suffice.
Also, the needs of the databases were different, so quite early, java.sql.Date was introduced, with its own limitations.
Because neither covered different calendars and time zones well, the Calendar API was introduced.
This still did not cover the complexity of the time zones. And yet, the mix of the above APIs was really a pain to work with. So as Java developers started working on global web applications, libraries that targeted most use cases, like JodaTime, got quickly popular. JodaTime was the de facto standard for about a decade.
But the JDK did not integrate with JodaTime, so working with it was a bit cumbersome. So, after a very long discussion on how to approach the matter, JSR-310 was created mainly based on JodaTime.
How to deal with it in Java's java.time
Determine what type to parse a timestamp to
When you are consuming a timestamp string, you need to know what information it contains. This is the crucial point. If you don't get this right, you end up with a cryptic exceptions like "Can't create Instant", "Zone offset missing", "unknown zone id", etc.
Unable to obtain OffsetDateTime from TemporalAccessor
Unable to obtain ZonedDateTime from TemporalAccessor
Unable to obtain LocalDateTime from TemporalAccessor
Unable to obtain Instant from TemporalAccessor
Does it contain the date and the time?
Does it have a time offset?
A time offset is the +hh:mm part. Sometimes, +00:00 may be substituted with Z as 'Zulu time', UTC as Universal Time Coordinated, or GMT as Greenwich Mean Time. These also set the time zone.
For these timestamps, you use OffsetDateTime.
Does it have a time zone?
For these timestamps, you use ZonedDateTime.
Zone is specified either by
name ("Prague", "Pacific Standard Time", "PST"), or
"zone ID" ("America/Los_Angeles", "Europe/London"), represented by java.time.ZoneId.
The list of time zones is compiled by a "TZ database", backed by ICAAN.
According to ZoneId's javadoc, the zone id's can also somehow be specified as Z and offset. I'm not sure how this maps to real zones.
If the timestamp, which only has a TZ, falls into a leap hour of time offset change, then it is ambiguous, and the interpretation is subject of ResolverStyle, see below.
If it has neither, then the missing context is assumed or neglected. And the consumer has to decide. So it needs to be parsed as LocalDateTime and converted to OffsetDateTime by adding the missing info:
You can assume that it is a UTC time. Add the UTC offset of 0 hours.
You can assume that it is a time of the place where the conversion is happening. Convert it by adding the system's time zone.
You can neglect and just use it as is. That is useful e.g. to compare or subtract two times (see Duration), or when you don't know and it doesn't really matter (e.g., local bus schedule).
Partial time information
Based on what the timestamp contains, you can take LocalDate, LocalTime, OffsetTime, MonthDay, Year, or YearMonth out of it.
If you have the full information, you can get a java.time.Instant. This is also internally used to convert between OffsetDateTime and ZonedDateTime.
Figure out how to parse it
There is an extensive documentation on DateTimeFormatter which can both parse a timestamp string and format to string.
The pre-created DateTimeFormatters should cover more or less all standard timestamp formats. For instance, ISO_INSTANT can parse 2011-12-03T10:15:30.123457Z.
If you have some special format, then you can create your own DateTimeFormatter (which is also a parser).
private static final DateTimeFormatter TIMESTAMP_PARSER = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SX"))
.toFormatter();
I recommend to look at the source code of DateTimeFormatter and get inspired on how to build one using DateTimeFormatterBuilder. While you're there, also have a look at ResolverStyle which controls whether the parser is LENIENT, SMART or STRICT for the formats and ambiguous information.
TemporalAccessor
Now, the frequent mistake is to go into the complexity of TemporalAccessor. This comes from how the developers were used to work with SimpleDateFormatter.parse(String). Right, DateTimeFormatter.parse("...") gives you TemporalAccessor.
// No need for this!
TemporalAccessor ta = TIMESTAMP_PARSER.parse("2011-... etc");
But, equipped with the knowledge from the previous section, you can conveniently parse into the type you need:
OffsetDateTime myTimestamp = OffsetDateTime.parse("2011-12-03T10:15:30.123457Z", TIMESTAMP_PARSER);
You do not actually need to the DateTimeFormatter either. The types you want to parse have the parse(String) methods.
OffsetDateTime myTimestamp = OffsetDateTime.parse("2011-12-03T10:15:30.123457Z");
Regarding TemporalAccessor, you can use it if you have a vague idea of what information there is in the string, and want to decide at runtime.
I hope I shed some light of understanding onto your soul :)
Note: There's a backport of java.time to Java 6 and 7: ThreeTen-Backport. For Android it has ThreeTenABP.
[3] Not just that they are not stripes, but there also some weird extremes. For instance, some neighboring Pacific Islands have +14:00 and -11:00 time zones. That means, that while on one island, there is 1st May 3 PM, on another island not so far, it is still 30 April 12 PM (if I counted correctly :) )
Another thing to note with LocalDateTime.parse is that you cannot use it with a custom formatter with only date formatter characters, such as uuuuMMdd. In this case, you should use LocalDate.parse instead. For example:
String s = "20210223";
// ok
LocalDate.parse(s, DateTimeFormatter.ofPattern("uuuuMMdd"));
// java.time.format.DateTimeParseException
LocalDateTime.parse(s, DateTimeFormatter.ofPattern("uuuuMMdd"));
Get the current UTC time in the required format
// Current the UTC time
OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);
// Get LocalDateTime
LocalDateTime localDateTime = utc.toLocalDateTime();
System.out.println("*************" + localDateTime);
// Formatted UTC time
DateTimeFormatter dTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
System.out.println(" formats as " + dTF.format(localDateTime));
// Get the UTC time for the current date
Date now = new Date();
LocalDateTime utcDateTimeForCurrentDateTime = Instant.ofEpochMilli(now.getTime()).atZone(ZoneId.of("UTC")).toLocalDateTime();
DateTimeFormatter dTF2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
System.out.println(" formats as " + dTF2.format(utcDateTimeForCurrentDateTime));
All the answers are good. The Java 8+ versions have these patterns for parsing and formatting time zones: V, z, O, X, x, Z.
Here's they are, for parsing, according to rules from the documentation:
Symbol Meaning Presentation Examples
------ ------- ------------ -------
V time-zone ID zone-id America/Los_Angeles; Z; -08:30
z time-zone name zone-name Pacific Standard Time; PST
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z zone-offset offset-Z +0000; -0800; -08:00;
But how about formatting?
Here's a sample for a date (assuming ZonedDateTime) that show these patters behavior for different formatting patters:
// The helper function:
static void printInPattern(ZonedDateTime dt, String pattern) {
System.out.println(pattern + ": " + dt.format(DateTimeFormatter.ofPattern(pattern)));
}
// The date:
String strDate = "2020-11-03 16:40:44 America/Los_Angeles";
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss zzzz");
ZonedDateTime dt = ZonedDateTime.parse(strDate, format);
// 2020-11-03T16:40:44-08:00[America/Los_Angeles]
// Rules:
// printInPattern(dt, "V"); // exception!
printInPattern(dt, "VV"); // America/Los_Angeles
// printInPattern(dt, "VVV"); // exception!
// printInPattern(dt, "VVVV"); // exception!
printInPattern(dt, "z"); // PST
printInPattern(dt, "zz"); // PST
printInPattern(dt, "zzz"); // PST
printInPattern(dt, "zzzz"); // Pacific Standard Time
printInPattern(dt, "O"); // GMT-8
// printInPattern(dt, "OO"); // exception!
// printInPattern(dt, "OO0"); // exception!
printInPattern(dt, "OOOO"); // GMT-08:00
printInPattern(dt, "X"); // -08
printInPattern(dt, "XX"); // -0800
printInPattern(dt, "XXX"); // -08:00
printInPattern(dt, "XXXX"); // -0800
printInPattern(dt, "XXXXX"); // -08:00
printInPattern(dt, "x"); // -08
printInPattern(dt, "xx"); // -0800
printInPattern(dt, "xxx"); // -08:00
printInPattern(dt, "xxxx"); // -0800
printInPattern(dt, "xxxxx"); // -08:00
printInPattern(dt, "Z"); // -0800
printInPattern(dt, "ZZ"); // -0800
printInPattern(dt, "ZZZ"); // -0800
printInPattern(dt, "ZZZZ"); // GMT-08:00
printInPattern(dt, "ZZZZZ"); // -08:00
In the case of positive offset, the + sign character is used everywhere (where there is - now) and never omitted.
This well works for new java.time types. If you're about to use these for java.util.Date or java.util.Calendar - not all going to work as those types are broken (and so marked as deprecated, please don't use them).
Let's take two questions, example string "2014-04-08 12:30"
How can I obtain a LocalDateTime instance from the given string?
import java.time.format.DateTimeFormatter
import java.time.LocalDateTime
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
// Parsing or conversion
final LocalDateTime dt = LocalDateTime.parse("2014-04-08 12:30", formatter)
dt should allow you to all date-time related operations
How can I then convert the LocalDateTime instance back to a string with the same format?
final String date = dt.format(formatter)
The universal method looks as below. It works for:
yyyy-MM-dd HH:mm:ss.SSS
yyyy-MM-dd HH:mm:ss.S
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm
yyyy-MM-dd HH
yyyy-MM-dd
public static final String DATE_FORMAT_YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
public LocalDateTime stringToLocalDateTime(String s){
return LocalDateTime.parse(s, DateTimeFormatter.ofPattern(DATE_FORMAT_YYYY_MM_DD_HH_MM_SS_SSS.substring(0, s.length())));
}
I found it wonderful to cover multiple variants of date time formats like this:
final DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"))
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);
There are already many good answers to this question. This answer shows how to use predefined DateTimeFormatters to build a DateTimeFormatter which can parse the given date-time string.
However, formatting the obtained LocalDateTime using this DateTimeFormatter will return a string with time in HH:mm:ss format. To restrict the time string to HH:mm format, we still have to use the pattern uuuu-MM-dd HH:mm as other answers have done.
Demo:
class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter(Locale.ENGLISH);
String strDateTime = "2014-04-08 12:30";
LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
System.out.println(ldt);
// However, formatting the obtained LocalDateTime using this DateTimeFormatter
// will return a string with time in HH:mm:ss format. To restrict the time
// string to HH:mm format, we still have to use the pattern, uuuu-MM-dd HH:mm as
// other answers have done.
String strDateTimeFormatted = ldt.format(dtf);
System.out.println(strDateTimeFormatted);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm", Locale.ENGLISH);
strDateTimeFormatted = ldt.format(formatter);
System.out.println(strDateTimeFormatted);
}
}
Output:
2014-04-08T12:30
2014-04-08 12:30:00
2014-04-08 12:30
ONLINE DEMO
Note: Here, you can use y instead of u but I prefer u to y.
Learn more about the modern Date-Time API from Trail: Date Time.

Is there YYYYWW Format in java

Is there any way to use Date in Java with the format YYYYWW? There is week of month but is there any way to find week of the year?
I am not quite sure about your question, but maybe you want a ISO-like week-date with year and week-of-year. If so then pay attention to the fact that there is another definition of a year, namely a year of weekdate (or other call it week-based-year). This year is in most cases the same as the standard calendar year but can differ at the begin or end of the calendar year dependent on the ISO-week-rules (monday as first day of week and first week-of-year having at least 4 days in calendar year).
If you look for this week-based-year and the ISO-week-of-year then you should use this expression:
// In France ISO-8601-week-rules are valid, so let's use this locale to choose ISO.
SimpleDateFormat sdf = new SimpleDateFormat("YYYYww", Locale.FRANCE); // big letter Y!
Otherwise you can of course just go with the other answer of #BetaRide: "yyyyww".
Standard Format
The ISO 8601 standard defines such week-of-year. You may want to review the Wikipedia articles here and here for guidance, as your format is not quite standard and is ambiguous. The standard uses a W and optionally a hyphen, such as YYYY-Www.
Joda-Time
The Joda-Time library has good support for ISO 8601 including weeks. See the ISODateTimeFormat class and its weekYearWeek method amongst others.
Note that time zone is crucial in determining a date and therefore a week. At the stroke of midnight ending Sunday in Paris means a new week in France while still "last week" in Montréal.
Example code using Joda-Time 2.5.
DateTime now = DateTime.now( DateTimeZone.forID( "America/Montreal" ) );
String output = ISODateTimeFormat.weekyearWeek().print( now );
int weekNumber = now.getWeekOfWeekyear();
When run.
now: 2014-11-03T02:30:10.124-05:00
output: 2014-W45
Avoid j.u.Date
The java.util.Date and .Calendar and SimpleDateFormat classes bundled with Java are notoriously troublesome. Avoid them. Use either Joda-Time or the new java.time package in Java 8 (inspired by Joda-Time).
You can use SimpleDateFormat to format and parse any date string.
The format you are looking for is "yyyyww".
Letter y represent Year where as be careful with - as w represents Week in year and W represents Week in month
try
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyww");
System.out.println(dateFormat.format(new Date()));
Refer this for more date-formats
yes we can use Y for week of the month and y for week of the year.
Ex: Date d =new Date();
SimpleDateFormat ft =
new SimpleDateFormat ("yyyyww");
System.out.println(ft.format(d));
can give you the current year and week.

Categories

Resources