I get date and time from client in the controller, here the signature of the function:
public ResponseEntity<Meeting> create(#RequestParam(name = "start") #DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime start)
if I print the start variable it shows date and time in 24-hour format:
2020-12-10T16:52:42.014982500
But I want the value of the LocalDateTime variable will be in 12 hours format, so I tried to change DateTimeFromat in the function's signature
public ResponseEntity<Meeting> create(#RequestParam(name = "start") #DateTimeFormat(DateTimeFormatter.ofPattern("dd/MM/yyyy hh.mm aa")) LocalDateTime start).3
But on this row:
DateTimeFormatter.ofPattern("dd/MM/yyyy hh.mm aa")
I get error:
Attribute value must be constant
My question is what params #DateTimeFormat have to get so it can convert date and time from client to 12 hours format?
A date-time object does not store the formatting information. A LocalDateTime is supposed to store just the date and time components (i.e. year, month, day of the month, hour, minute, second and the fraction of second). When you print an object of LocalDateTime, you get what its toString function returns. If you need the value in a different format, you need to get a formatted string out of this object but in no case, you will be able to store the format into the instance of LocalDateTime.
Given below is a simple demo:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
class Main {
public static void main(String[] args) {
String strDateTime = "2020-12-10T16:52:42.014982500";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/uuuu hh.mm a", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime);
System.out.println(ldt);// Prints the value of ldt#toString
// Get a formatted string
String formatted = ldt.format(dtf);
System.out.println(formatted);
}
}
Output:
2020-12-10T16:52:42.014982500
10/12/2020 04.52 PM
Update
From your comment on the other answer (which has been deleted now), I learnt that your date-time string is 2020-12-08T21:34:18.119+00:00 which has a zone offset information (+00:00) and therefore, the most appropriate type would be OffsetDateTime.
Change the annotation as
public ResponseEntity<Meeting> create(#RequestParam(name = "start") #DateTimeFormat(pattern = DateTimeFormatter.ISO_ZONED_DATE_TIME) OffsetDateTime start)
or
public ResponseEntity<Meeting> create(#RequestParam(name = "start") #DateTimeFormat(iso = ISO.DATE_TIME) OffsetDateTime start)
Check the Spring documentation page to learn more about the second option.
A quick demo:
import java.time.OffsetDateTime;
class Main {
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.parse("2020-12-08T21:34:18.119+00:00");
System.out.println(odt);
}
}
Output:
2020-12-08T21:34:18.119Z
Related
I have a ZULU timestamp that I have to convert into Paris time zone.
ZULU 2022-11-04T06:10:08.606+00:00 --> Paris 2022-11-04T07:10:08.606+01:00
And have to take care of DST for example:
Summer time Hour +2 hour
Winter time Hour +1 hour
I have written the below code which is working as expected on the local but when deploy on the server (Paris) not working as expected.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Locale;
public class ParisTime {
public static void main(String[] args) throws ParseException {
// String date = "2022-05-31T23:30:12.209+00:00";
String date = "2022-11-04T06:10:08.606+00:00";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ENGLISH);
LocalDateTime dateTime = dateFormat.parse(date).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
ZonedDateTime of = ZonedDateTime.of(dateTime, ZoneId.of("Europe/Paris"));
String hourDiff = of.toString().substring(of.toString().indexOf('+') + 1, of.toString().indexOf('+') + 3);
String zonedDateTime = of.plusHours(Integer.valueOf(hourDiff)).toString();
String newDatetime = zonedDateTime.substring(0, of.toString().indexOf('['));
System.out.println(newDatetime);
System.out.println(dateFormat.parse(newDatetime));
}
}
Output
2022-11-04T07:10:08.606+01:00
Fri Nov 04 07:10:08 IST 2022
You can directly switch between zones and offsets using plain java.time, no legacy baggage necessary…
Here's how:
your input example is an ISO-formatted datetime with an offset from UTC (of 0 hours and 0 minutes, so it is Zulu time respectively in UTC), which means you can parse it in one go to a java.time.OffsetDateTime
an OffsetDateTime can be converted into a ZonedDateTime
a ZonedDateTime can handle daylight saving time (DST)
having a ZonedDateTime you can switch its ZoneId, which will respect DST, but keep the underlying instant
Please see the following example…
public static void main(String[] args) {
// input example
String date = "2022-11-04T06:10:08.606+00:00";
// directly parse it to a java.time.OffsetDateTime
OffsetDateTime odt = OffsetDateTime.parse(date);
// make the UTC/Zulu datetime zoned
ZonedDateTime zdt = odt.toZonedDateTime();
// print it
System.out.println(zdt);
// switch the zone to the desired one
ZonedDateTime zdtParis = zdt.withZoneSameInstant(ZoneId.of("Europe/Paris"));
// print that, too
System.out.println(zdtParis);
// or print a coversion to OffsetDateTime without explicitly mentioning the zone
System.out.println(zdtParis.toOffsetDateTime());
// the same can be achieved keeping the ZonedDateTime but formatting it as OffsetDateTime
System.out.println(zdtParis.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
}
The output of the above code is
2022-11-04T06:10:08.606Z
2022-11-04T07:10:08.606+01:00[Europe/Paris]
2022-11-04T07:10:08.606+01:00
2022-11-04T07:10:08.606+01:00
Try it with a datetime influenced by DST, you will see DST respected…
This is the output of the same code using the input value "2022-05-31T23:30:12.209+00:00":
2022-05-31T23:30:12.209Z
2022-06-01T01:30:12.209+02:00[Europe/Paris]
2022-06-01T01:30:12.209+02:00
2022-06-01T01:30:12.209+02:00
Your string is already in the format recognized by [static] method parse in class java.time.Instant. Then you can convert that instant to a ZonedDateTime in the Paris time zone. Two lines of code:
String date = "2022-11-04T06:10:08.606+00:00";
java.time.Instant inst = java.time.Instant.parse(date);
java.time.ZonedDateTime zdt = inst.atZone(java.time.ZoneId.of("Europe/Paris"));
It will also take into consideration changes for summer time and non-summer time.
ZULU : 2022-11-04T06:10:08.606Z
Paris: 2022-11-04T07:10:08.606+01:00[Europe/Paris]
String date = "08/02/2022 Tuesday";
DateTimeFormatter LONG_DATE_FORMAT_ddMMyyyyEEEE = ofPattern("dd/MM/yyyy EEEE");
LocalDate.parse(date, LONG_DATE_FORMAT_ddMMyyyyEEEE);
I'm getting a DateTimeParseException with the following message: Text 08/02/2022 Tuesday' could not be parsed at index 11.
I suppose this is an issue with the EEEE side of my format, but I can't seem to understand what should replace it.
This is java 1.8.0_311
We need DateTimeFormatter class to format date string properly. We also need to convert the string date to LocalDate object and back to string again to display. The DateTimeParseException class handles any undesired outcomes.
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
class Main {
public static void main(String[] args) {
try{
String date = "08-02-2022 Tuesday";
DateTimeFormatter pattern =
DateTimeFormatter.ofPattern("dd-MM-yyyy eeee");
// parsing string date to LocalDate obj
// The part you were missing
LocalDate formattedDate = LocalDate.parse(date, pattern);
// Again converting to string
System.out.println(formattedDate.format(pattern));
}
// handling exception for unparseble dates
catch(DateTimeParseException x){
System.out.println("The given date cannot be parsed");
}
}
}
LocalDate contains of a day, month, and year (Variation between +999999999-12-31 and -999999999-12-31)
Things like time and other values are rejected by the parsing. If you would like the day of the week, you can use a function like:
// Parses the date
LocalDate dt = LocalDate.parse("2018-11-27");
// Prints the day
System.out.println(dt.getDayOfWeek());
This works for me:
String date = "08/02/2022 Tuesday";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy EEEE");
LocalDate time = LocalDate.parse(date, formatter);
System.out.println(time.format(formatter));
I am trying to parse a datetimeStamp as below but I am not able to find the correct parser for it. Can someone advise how can I parse such dates:
import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;
public class HelloWorld{
public static void main(String []args){
int DAYS = 30;
String date ="2021-04-23T12:09:56.123-07:00";
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter
.ofPattern("YYYY-MM-DD'T'hh:mm:ss.SSS±hh:mm");
LocalDateTime localDateTime = LocalDateTime.parse(date, DATE_TIME_FORMATTER);
System.out.println("Local Date" + localDateTime);
LocalDateTime now = LocalDateTime.now();
if (localDateTime.isBefore(now) && localDateTime.isAfter(now.plusDays(DAYS)))
{
System.out.println("Date is incorrect");
}else{
System.out.println("Success");
}
}
}
Below is also a bit of additional detail:
Must be expressed in ISO 8601 extended format as one of the following - YYYY-MM-DDThh:mm:ss[ .sss ]Z, YYYY-MM-DDThh:mm:ss[ .sss ]±hh:mm . Where [ .sss ] is optional and can be 1 to 3 digits. Must be a value no more than 30 days in the future. Mastercard recommends using a value of (Current Time + 30 minutes). Max length - 29. Type - String.
example: "2015-07-04T12:09:56.123-07:00"
Please help me with the correct formatter for the day specified.
You have 3 separate problems here:
±hh:mm - as per the docs of DateTimeFormatter (remember, reading is fundamental! Always read the javadoc before asking SO questions!), ± isn't a thing. hh and mm are things, but not 'offset hours'. The 'pattern' that represents tz offsets is a single letter; you're most likely looking for Z. But that doesn't ordinarily include the :.
LocalDateTime cannot represent offsets and doesn't know about timezones. If you want that, you're looking for either ZonedDateTime or most likely OffsetDateTime.
Your pattern doesn't include a locale which means the output of it, and what it can parse, depends on the locale of the computer you run this code on, which sounds bad. Always use .ofPattern("someString", Locale.ENGLISH) (or some other locale) unless you are really really sure you want the app to depend on the configuration of the server you run it on, which should be very rare.
Get rid of this wrong pattern (and the DateTimeFormatter) at all and use an OffsetDateTime instead of a LocalDateTime which isn't able to store information about an offset.
This is a conversion of your code (slightly adjusted and commented):
public static void main(String[] args) {
String date = "2021-04-23T12:09:56.123-07:00";
/*
* no DateTimeFormatter needed due to default format of the String
*/
// use an OffsetDateTime to parse a String with an offset
OffsetDateTime odtParsed = OffsetDateTime.parse(date);
// print it
System.out.println("Parsed OffsetDateTime is " + odtParsed);
// take the current instant as an OffsetDateTime at an offset of -7 hours
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.ofHours(-7));
// run your check and get a success
if (odtParsed.isBefore(now) && odtParsed.isAfter(now.plusDays(DAYS))) {
System.out.println("Date is incorrect");
} else {
System.out.println("Success");
}
}
It prints
Parsed OffsetDateTime is 2021-04-23T12:09:56.123-07:00
Success
Hint: This will fail for differently formatted Strings. If the formattings only differ a little, you might be able to create a DateTimeFormatter (via a DateTimeFormatterBuilder) that can handle optional parts and so on.
Edit
If only the millis of day are optional and the format of the offset always consists of a plus or minus followed by two digits for hours, a colon and two digits for minutes, the following example might be showing a sufficient way of making it generic:
public static void main(String[] args) {
String date = "2021-04-23T12:09:56.123-07:00";
String date1 = "2021-04-23T12:09:56.123+02:00";
String date2 = "2021-04-23T12:09:56.123+00:00";
String date3 = "2021-04-23T12:09:56-07:00";
String date4 = "2021-04-23T12:09:56+02:00";
String date5 = "2021-04-23T12:09:56+00:00";
// DateTimeFormatter using optional millis of second
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[.SSS]xxx");
// use an OffsetDateTime to parse a String with an offset
OffsetDateTime odtParsed = OffsetDateTime.parse(date, dtf);
OffsetDateTime odtParsed1 = OffsetDateTime.parse(date1, dtf);
OffsetDateTime odtParsed2 = OffsetDateTime.parse(date2, dtf);
OffsetDateTime odtParsed3 = OffsetDateTime.parse(date3, dtf);
OffsetDateTime odtParsed4 = OffsetDateTime.parse(date4, dtf);
OffsetDateTime odtParsed5 = OffsetDateTime.parse(date5, dtf);
// print it
System.out.println("Parsed OffsetDateTime is " + odtParsed);
System.out.println("Parsed OffsetDateTime is " + odtParsed1);
System.out.println("Parsed OffsetDateTime is " + odtParsed2);
System.out.println("Parsed OffsetDateTime is " + odtParsed3);
System.out.println("Parsed OffsetDateTime is " + odtParsed4);
System.out.println("Parsed OffsetDateTime is " + odtParsed5);
}
Output:
Parsed OffsetDateTime is 2021-04-23T12:09:56.123-07:00
Parsed OffsetDateTime is 2021-04-23T12:09:56.123+02:00
Parsed OffsetDateTime is 2021-04-23T12:09:56.123Z
Parsed OffsetDateTime is 2021-04-23T12:09:56-07:00
Parsed OffsetDateTime is 2021-04-23T12:09:56+02:00
Parsed OffsetDateTime is 2021-04-23T12:09:56Z
and if you don't want an offset of zero hours and zero minutes to be output as a Z, then use the DateTimeFormatter for output like this:
OffsetDateTime odtParsed5 = OffsetDateTime.parse(date5, dtf);
which makes the output look like this:
Parsed OffsetDateTime is 2021-04-23T12:09:56.000+00:00
Where the millis of day are printed even if they are all zero.
Another Edit:
To check if the date is in the range 30 days in the past to 30 days in the future it might be good to use the date parts only:
public static void main(String[] args) {
// the first part is already known from the examples above...
String date = "2021-04-23T12:09:56.123-07:00";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[.SSS]xxx");
OffsetDateTime odtParsed = OffsetDateTime.parse(date, dtf);
// get the current instant as an OffsetDateTime (in UTC == +00:00)
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
/*
* might be smart to keep time of day out of the calculation, so...
*/
// get the date only out of the OffsetDateTime
LocalDate today = now.toLocalDate();
// create one for 30 days before
LocalDate thirtyDaysBeforeToday = today.minusDays(30);
// and one 30 days in the future
LocalDate thirtyDaysInTheFuture = today.plusDays(30);
// finally extract the date part from the parsed date time
LocalDate d = odtParsed.toLocalDate();
// make your checks using the LocalDates, maybe separate the two cases of an invalid date
if (d.isBefore(thirtyDaysBeforeToday)) {
System.err.println("Invalid date: too far in the past");
} else if (d.isAfter(thirtyDaysInTheFuture)) {
System.err.println("Invalid date: too far in the future");
} else {
System.out.println("Valid date");
}
}
Try some different valid and invalid dates...
Your documentation uses ± to mean either + or -, and its placeholders aren't the Java ones. Just use DateTimeFormatter.ISO_OFFSET_DATE_TIME.
This question already has answers here:
Parse CIM_DateTime with milliseconds to Java Date
(2 answers)
Closed 2 years ago.
Into a Java application I have this String representing a timestamp containing values like this: 2009-10-17 05:45:14.000
As you can see the string represents the year, the month, the day, the hour, the minute, the second and the millisencond.
I have to convert a String like this into a Date object (if possible bringing also the millisecond information, is it possible?)
How can I correctly implement it?
You can use SimpleDateFormat to parse a given string date according to a given pattern, it also supports milliseconds, like this:
SimpleDateFormat format= new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
Date date=format.parse("2009-10-17 05:45:14.050");
Since Java 8, you should use the classes in the date-time API
Class LocalDateTime stores a date and a time up to nanosecond precision.
Here is a snippet showing how to parse a string into an instance of LocalDateTime
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class DateTime {
public static void main(String[] args) {
String str = "2009-10-17 05:45:14.000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(str, formatter);
}
}
public static String convertInDateTimeSecondTOJodaTime(String dateTime) {
try {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
DateTime date = formatter.parseDateTime(dateTime).withZoneRetainFields(DateTimeZone.UTC);
return date.toString("h:mm aa");
} catch (Exception e) {
return null;
}
}
main(){
print(convertInDateTimeSecondTOJodaTime("2020-04-09T07:31:16Z"))
}
I am trying to convert given date-time in UTC format using joda date time it's giving wrong time it's given one hour before please help me what I am doing wrong.
The desired result is in London time, so 8:31 AM in this case.
import java.util.Date;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
public class CurrentUtcDate {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC Time is: " + dateFormat.format(date));
}
}
Output
UTC Time is: 22-01-2018 13:14:35
You can check here https://www.quora.com/How-do-I-get-the-current-UTC-date-using-Java
As you need to you use Joda DateTime, you need to use formatter of Joda.
You are returning date with pattern "h:mm aa" so I assume you need to extract time from the date.
Below code should work:
import java.util.Locale;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class MyDateCoonverter {
public static void main(String a[]) {
System.out.println(convertInDateTimeSecondTOJodaTime("2020-04-09T07:31:16Z"));
}
public static String convertInDateTimeSecondTOJodaTime(String dateTime) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
DateTime dt = formatter.parseDateTime(dateTime);
return dt.toString("h:mm aa", Locale.ENGLISH);
}
}
It gives output as:
7:31 AM
If you don't want to use any third party library & still want to extract only time from date, you can use Java's LocalTime.
If you are using Java 8 or newer, you should not use java.util.Date (deprecated) or Joda Time (replaced by the new DATE API of Java 8 with java.time package) :
public static void main(String[] args) {
String date = "2020-04-09T07:31:16Z";
String formatedDate = ZonedDateTime.parse(date).format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT));
System.out.println(formatedDate); //print "7:31 AM"
}
}
First, don’t handle date and time as strings in your program. Handle them as proper date-time objects. So but for all but the simplest throw-away programs you should not want a method that converts from a string in UTC to a string in London time in a different format.
So when you accept string input, parse into a DateTime object:
String stringInput = "2020-04-09T07:31:16Z";
DateTime dt = DateTime.parse(stringInput);
System.out.println("Date-time is: " + dt);
Output so far is:
Date-time is: 2020-04-09T07:31:16.000Z
I am exploiting the fact that your string is in ISO 8601 format, the default for Joda-Time, so we need no explicit formatter for parsing it.
Not until you need to give string output, convert your date and time to the desired zone and format into the desired string:
DateTimeZone zone = DateTimeZone.forID("Europe/London");
DateTime outputDateTime = dt.withZone(zone);
String output = outputDateTime.toString("h:mm aa");
System.out.println("Output is: " + output);
Output is: 8:31 AM
What went wrong in your code
Z in single quotes in your format pattern string is wrong. Z in your input string is an offset of 0 from UTC and needs to be parsed as an offset, or you are getting an incorrect result. Never put those quotes around Z.
withZoneRetainFields() is the wrong method to use for converting between time zones. The method name means that the date and hour of day are kept the same and only the time zone changed, which typically leads to a different point in time.
What happened was that your string was parsed into 2020-04-09T07:31:16.000+01:00, which is the same point in time as 06:31:16 UTC, so wrong. You next substituted the time zone to UTC keeping the time of day of 07:31:16. This time was then formatted and printed.
Do consider java.time
As Fabien said, Joda-Time has later been replaced with java.time, the modern Java date and time API. The Joda-Time home page says:
Note that Joda-Time is considered to be a largely “finished” project.
No major enhancements are planned. If using Java SE 8, please migrate
to java.time (JSR-310).
Links
Wikipedia article: ISO 8601
Joda-Time home