This question might sound similar to most of the other questions asked here on Stackoverflow but I could not figure out my problem.
I want to parse the string value into a date.
String dateTime = "23 Oct 2020 02:44:58 +1000"
The solution to this problem is:
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.parseCaseInsensitive();
builder.appendPattern("d MMM yyyy HH:mm[:ss] Z");
DateTimeFormatter dtf = builder.toFormatter();
ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateTime, dtf);
Instant instant = zonedDateTime.toInstant();
Date finalDate = Date.from(instant);
If I want to parse the date with timezone instead like String dateTime = "23 Oct 2020 02:44:58 AEST" then I need to change the builder.appendPattern("d MMM yyyy HH:mm[:ss] Z"); from capital Z to small z as mentioned here.
The question here is how would I make my parser flexible enough for it to handle either timezone or offset value?
Note. I have used [ss] as the seconds' field is optional. And as per documentation using VV was similar to z while 'V' did not work for me.
You can add them as optional parts to the formatter, just like you did with the seconds part:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("d MMM yyyy HH:mm[:ss] [Z][z]")
.toFormatter(Locale.ROOT);
Online demo
[ and ] denote an optional part: the corresponding text is consumed if it can be successfully parsed by means of the pattern within the brackets, otherwise, no text is consumed and the pattern within is skipped.
You can try using try-catch block
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.parseCaseInsensitive();
builder.appendPattern("d MMM yyyy HH:mm[:ss] Z");
DateTimeFormatter dtf = builder.toFormatter();
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.parseCaseInsensitive();
builder.appendPattern("d MMM yyyy HH:mm[:ss] z");
DateTimeFormatter dtf = builder.toFormatter();
ZonedDateTime zonedDateTime;
try {
zonedDateTime = ZonedDateTime.parse(dateTime, dtf1);
} catch (DateTimeParseException e) {
zonedDateTime = ZonedDateTime.parse(dateTime, dtf2);
}
Instant instant = zonedDateTime.toInstant();
Date finalDate = Date.from(instant);
Related
How to convert date format "2021-02-28 13:38:00.597+0000" to "Mon, Feb 28,2021 15:25:00 UTC" UTC format in Scala?
If you are using an older Java version prior to Java 8, it's best to use the DateTimeFormat from joda-time. BTW, the +0000 zone offset is for UTC, so I could have omitted withZoneUTC(), but I still used it for the first date just to be safe:
val oldDateString = "2021-02-28 13:38:00.597+0000"
val OldFormat = "yyyy-MM-dd HH:mm:ss.SSSZ"
val NewFormat = "EEE, MMM dd, yyyy HH:mm:ss z"
val formatterOld = DateTimeFormat.forPattern(OldFormat)
val formatterNew = DateTimeFormat.forPattern(NewFormat)
val dt = formatterOld.withZoneUTC().parseDateTime(oldDateString)
val dateStringInUTC = formatterNew.withZoneUTC().print(dt)
println(dt) // 2021-02-28T13:38:00.597Z
println(dateStringInUTC) // Sun, Feb 28, 2021 13:38:00 UTC
UPDATE: For Java 8 and newer, the java.time API is your friend. Similarly, withZoneSameInstant(ZoneOffset.UTC) was not really needed:
val oldDateString = "2021-02-28 13:38:00.597+0000"
val OldFormat = "yyyy-MM-dd HH:mm:ss.SSSZZZ"
val NewFormat = "EEE, MMM dd, yyyy HH:mm:ss z"
val formatterOld = DateTimeFormatter.ofPattern(OldFormat)
val formatterNew = DateTimeFormatter.ofPattern(NewFormat)
val zdt = ZonedDateTime.parse(oldDateString, formatterOld)
val dateStringInUTC = zdt.withZoneSameInstant(ZoneId.of("UTC")).format(formatterNew)
println(zdt) // 2021-02-28T13:38:00.597Z
println(dateStringInUTC) // Sun, Feb 28, 2021 13:38:00 UTC
UPDATE: Switched to using ZoneId.of("UTC") instead of ZoneOffset.UTC because the latter does not get the String UTC printed at the end, even though ZoneOffset extends ZoneId, as #deHaar mentioned.
If you could use java.time, you would need
a DateTimeFormatter for parsing Strings with the format of your input example, which is quite near to ISO standard, but is missing the 'T' between date and time of day
another DateTimeFormatter for outputting the temporal content in the desired format, which includes (English) abbreviations for day of week and month of year
an OffsetDateTime for parsing the String with the first DateTimeFormatter and
a ZonedDateTime for the temporal value in UTC
This is how I would do it in Java:
public static void main(String[] args) {
// example String
String utcDatetimeString = "2021-02-28 13:38:00.597+0000";
// prepare a formatter that can parse a String of this format
DateTimeFormatter dtfIn = DateTimeFormatter.ofPattern(
"uuuu-MM-dd HH:mm:ss.SSSxxxx",
Locale.ENGLISH
);
// parse it to an OffsetDateTime
OffsetDateTime odt = OffsetDateTime.parse(utcDatetimeString, dtfIn);
// then convert it to a ZonedDateTime applying UTC zone
ZonedDateTime zdt = odt.atZoneSameInstant(ZoneId.of("UTC"));
// prepare a formatter that produces the desired output
DateTimeFormatter dtfOut = DateTimeFormatter.ofPattern(
"EEE, MMM dd, uuuu HH:mm:ss zzz",
Locale.ENGLISH
);
// and print the ZonedDateTime using the formatter
System.out.println(zdt.format(dtfOut));
}
Output:
Sun, Feb 28, 2021 13:38:00 UTC
I am trying to convert a string to date format with Java8 using DateTimeFormatter in spring boot, But I receive an error [[java.time.format.DateTimeParseException: Text '10-03-2021' could not be parsed at index 0]]. I am using LocalDate because I want my output to have only date without time. What Am I doing wrong in my code.
String date= "10-03-2021"
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE, MMM d, yyyy",Locale.forLanguageTag("sw-TZ"));
LocalDateTime dateTime = LocalDateTime.parse(date, formatter);
System.out.println(dateTime.format(formatter));
You need to parse date in dd-MM-yyyy pattern first and then format it to the pattern of your choice.
String date= "10-03-2021";
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd-MM-yyyy");
LocalDate localDate = LocalDate.parse(date, format);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE, MMM d, yyyy",Locale.forLanguageTag("sw-TZ"));
System.out.println(localDate.format(formatter));
I want to convert elements of an array list into ZonedDateTime object after parsing them. A string is shown below.
"2017-02-12 06:59:00 +1300"
At the moment I use the DateTimeFormatter:
DateTimeFormatter dateTimeFormatter =
DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss ZZ");
And try to use parse, to get the time:
this.actionTime = dateTimeFormatter.parse(actionTime, ZonedDateTime::from);
See below method:
public DateCalculatorTest(String actionTime, int expectedDayOfWeek) {
DateTimeFormatter dateTimeFormatter =
DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss ZZ");
DateTimeFormatter localTimeFormatter =
DateTimeFormatter.ofPattern("YYYY-MM-dd");
this.actionTime = dateTimeFormatter.parse(actionTime, ZonedDateTime::from);
this.expectedDayOfWeek = expectedDayOfWeek;
}
However, I am not able to parse the string. I get the following error:
Text '2017-02-12 06:59:00 +1300' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {WeekBasedYear[WeekFields[SUNDAY,1]]=2017, DayOfMonth=12, MonthOfYear=2, OffsetSeconds=46800},ISO resolved to 06:59 of type java.time.format.Parsed
Is there a way to do this with java.time?
In the DateTimeFormatter years should be small letters. Replace
YYYY-MM-dd HH:mm:ss ZZ
with
yyyy-MM-dd HH:mm:ss ZZ
And you don't require two ZZ, single is enough. In your code the ZoneId instance will give you default ZoneId. It will fall back to LocalDateTime. If you want to specify the ZoneId use the following
this.actionTime = ZonedDateTime.parse(actionTime, dateTimeFormatter.withZone(ZoneId.of(<<yourxoneid>>)));
I managed to fix this using the following:
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss ZZ");
DateTimeFormatter localTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
this.symbol = symbol;
this.actionTime = ZonedDateTime.parse(actionTime, dateTimeFormatter);
this.actionDate = LocalDate.parse(expectedResult, localTimeFormatter);
I have a date-time from Los_Angeles. The daylight saving applies when possible. I'm trying to convert that date-time into a timestamp, but I don't seem to understand the Java 8 DateTime API. The following snippet returns 1238112000 (which is the correct date if it was specified in UTC). What should I change to show 1238137200 instead?
String date = "March 27, 2009 00:00:00";
DateTimeFormatter formatter = DateTimeFormatter.
ofPattern("MMMM dd, yyyy HH:mm:ss", Locale.ENGLISH).
withZone(ZoneId.of("America/Los_Angeles"));
LocalDateTime.parse(date, formatter).toEpochSecond(ZoneOffset.UTC))
By parsing the date into a LocalDateTime, you are ignoring the timezone information from the formatter. You should use a ZonedDateTime:
public static void main(String[] args) {
String date = "March 27, 2009 00:00:00";
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("MMMM dd, yyyy HH:mm:ss", Locale.ENGLISH)
.withZone(ZoneId.of("America/Los_Angeles"));
long second = ZonedDateTime.parse(date, formatter).toEpochSecond();
System.out.println(second); // prints "1238137200"
}
On the returned instance, you can then call toEpochSecond().
I have to parse a date string (e.g. "October 2015") to a Date.
So the question is: how can I parse a date of MMMM yyyy format? Its ok if the new Date object is the first month of the given month.
I tried:
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("MMMM yyyy").toFormatter();
TemporalAccessor ta = formatter.parse(node.textValue());
Instant instant = LocalDate.from(ta).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
Date d = Date.from(instant);
But it does not work since the day is missing.
What you have there is a YearMonth, not a LocalDate since the day is missing.
The following works:
String string = "October 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM yyyy", Locale.ENGLISH);
YearMonth yearMonth = YearMonth.parse(string, formatter);
// Alternatively: YearMonth yearMonth = formatter.parse(string, YearMonth::from);
LocalDate date = yearMonth.atDay(1);
System.out.println(yearMonth); // prints "2015-10"
System.out.println(date); // prints "2015-10-01"
If you then want that as a java.util.Date, you need to specify which time zone you mean, maybe UTC or system default?
// ZoneId zone = ZoneOffset.UTC;
ZoneId zone = ZoneId.systemDefault();
Date javaUtilDate = Date.from(date.atStartOfDay(zone).toInstant());
System.out.println(javaUtilDate); // prints "Thu Oct 01 00:00:00 CEST 2015"
// because i'm in Europe/Stockholm.
How about this
DateFormat format = new SimpleDateFormat("MMMM yyyy", Locale.ENGLISH);
Date date = format.parse("October 2015");
System.out.println(date); // Prints Thu Oct 01 00:00:00 BST 2015
For java 8
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("MMMM yyyy")
.toFormatter(Locale.US);
TemporalAccessor ta = formatter.parse("October 2015");
YearMonth ym = YearMonth.from(ta);
LocalDateTime dt = LocalDateTime.of(ym.getYear(), ym.getMonthValue(),
1, 0, 0, 0);
Instant instant = Instant.from(dt.atZone(ZoneId.systemDefault()));
Date d = Date.from(instant);
You can use SimpleDateFormat's parse method for that
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMMMM yyyy"); //MMMM yyyy example: October 2015
public Date getDateFromString(String input) {
return DATE_FORMAT.parse(input);
}
For more information, see: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html#parse(java.lang.String,%20java.text.ParsePosition)
Explanation of format:
MMMM indicates you are parsing full name months such as "October"
yyyy indicates you have 4-digit length years. If you wanted to parse for example, October 15, your format would look like this: "MMMM yy"
Why not use a SimpleDateFormatter?
This works fine for me:
SimpleDateFormat formatter = new SimpleDateFormat("MMMM yyyy");
Date d = formatter.parse("Oktober 2015");