Parse exception in joda-time parsing day and time - java

The problem is pretty simple, I have a TimerTask that is going to be scheduled daily or weekly. (Depends on the given start date and period in config file).
So in config file I specify the day of week and time of execution with period between executions. But Joda-Time refuses to work with my date :(
Here is basic input:
String input = "Tue 12:00:00";
DateTimeFormatter formatter = DateTimeFormat.forPattern("EEE HH:mm:ss");
DateTime dateTime = DateTime.parse(input, formatter); // Here parse exception is thrown...
Exception message: java.lang.IllegalArgumentException: Invalid format: "Tue 12:00:00"
Could someone explain me why I cannot parse this date like that and maybe point me into right direction to solve this kind of problem. Of course I could manually parse the date and set things in calendar, but I don't want to reinvent the wheel if there is something like Joda-Time that could do it for me.

The weekday text Tue probably doesnt match that of your default locale.
DateTimeFormatter formatter =
DateTimeFormat.forPattern("EEE HH:mm:ss").withLocale(Locale.ENGLISH);

You can use Locale. The following code is working fine.
import java.util.Locale;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class Test22 {
public static void main(String[] args) {
// TODO Auto-generated method stub
DateTime currentDate = new DateTime();
DateTimeFormatter dtf = DateTimeFormat.forPattern("EEE HH:mm:ss").withLocale(Locale.ENGLISH);
String formatedDate = dtf.print(currentDate);
System.out.println(formatedDate);
DateTime now = dtf.parseDateTime(formatedDate);
System.out.println(now);
}
}
Output:
Thu 23:36:33
2000-12-28T23:36:33.000+06:00
Resource Link: https://stackoverflow.com/a/41465180/2293534

Related

Parse Timestamp in Java

I get a timestamp in the format "20210908094049.884Z". This is the last modify timestamp from an LDAP object. I use Spring Boot Ldap. I have no clue how to parse this String in a Datetime like dd.MM.yyyy HH:mm.
Can anyone help me please?
Here is an example:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Main {
public static void main(String[] args) {
// Creating new simple date formatter with the format you've given
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
// Defining the input date
String inputDate = "20210908094049.884Z";
// Parsing the date, catching the parse exception if date is malformatted
Date date = null;
try {
// Date ends on a Z, we remove this Z (Z is for timezone UTC +0:00)
date = format.parse(inputDate.replace("Z", ""));
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
Giving following output:
Wed Sep 08 09:40:49 CEST 2021
Edit:
Here another even better solution from Ole V.V.
import java.time.Instant;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
Instant instant = DateTimeFormatter
// Defining pattern to parse
.ofPattern("yyyyMMddHHmmss.SSSXX")
// Defining input to parse with pattern
.parse("20210908094049.884Z", Instant::from);
System.out.println(instant);
}
}
Output is an instant with value:
2021-09-08T09:40:49.884Z
java.time
I recommend that you use java.time, the modern Java date and time API, for your work with timestamps.
The LDAP timestamp format has a number of allowed variations (see the link at the bottom). The following formatter takes many of them into account, not all of them.
private static final DateTimeFormatter LDAP_PARSER = new DateTimeFormatterBuilder()
.appendPattern("uuuuMMddHHmmss")
.optionalStart()
.appendPattern("[.][,]")
.appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, false)
.optionalEnd()
.appendPattern("[XX][X]")
.toFormatter(Locale.ROOT);
With this formatter we may for example parse your string into an OffsetDateTime:
String ldapTimestampString = "20210908094049.884Z";
OffsetDateTime timestamp = OffsetDateTime.parse(ldapTimestampString, LDAP_PARSER);
System.out.println(timestamp);
Output is:
2021-09-08T09:40:49.884Z
Formatting
To convert the timestamp to a string containing date and time you need to decide on a time zone for that since it is never the same date nor the same time in all time zones.
Use this formatter:
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
Then do:
ZoneId zone = ZoneId.of("Pacific/Tarawa");
ZonedDateTime dateTime = timestamp.atZoneSameInstant(zone);
String formattedDateTime = dateTime.format(FORMATTER);
System.out.println(formattedDateTime);
08.09.2021 21:40
Links
Oracle tutorial: Date Time explaining how to use java.time.
GeneralizedTime on ldapwiki defining the LDAP timestamp format.

How to format Date object to match #JsonFormat?

I have a json formatted response Date to the controller that is like this:
#JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "America/Chicago")
private Date date;
So when I make a post call, it would look like:
"date": "2021-08-20 14:17:43"
So the response string would look something like this {"date":"2021-05-21 14:23:44"}. In JUnit, I am manually creating a response object and setting the Date object so I can then use Gson to turn it into a string and then assert that the two are equal.
I am trying to match this in my SpringMVC JUnit test case by trying to do:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
String formattedDate = sdf.format(new Date());
LocalDate localDate = LocalDate.parse(formattedDate);
Date date = Date.from(localDate.atStartOfDay(ZoneId.of("America/Chicago")).toInstant());
But it is having an error parsing it because of the space between yyyy-MM-dd and HH:mm:ss:
java.time.format.DateTimeParseException: Text '2021-08-20 14:23:44' could not be parsed, unparsed text found at index 10
I think I may be doing this inefficiently, so I was wondering if there was a more simple way to make a Date object that would match the format of #JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "America/Chicago")
I'm trying to match the response body so it passes via mockito.
Do not mix the modern and the legacy Date-Time API
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDate = "2021-08-20 14:17:43";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDate, dtf);
System.out.println(ldt);
// Get the required Instant
ZonedDateTime zdtUtc = ldt.atZone(ZoneOffset.UTC);
ZonedDateTime zdtChicago = zdtUtc.withZoneSameInstant(ZoneId.of("America/Chicago"));
Instant instant = zdtChicago.toInstant();
System.out.println(instant);
}
}
Output:
2021-08-20T14:17:43
2021-08-20T14:17:43Z
ONLINE DEMO
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*. However, for any reason, if you need to convert this object of Instant to an object of java.util.Date, you can do so as follows:
Date date = Date.from(instant);
Learn more about the modern Date-Time API from Trail: Date Time.
* 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.
you could be missing date deserializer
#JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
#JsonDeserialize(using = LocalDateTimeDeserializer.class)
Posting this to only try and satisfy what you're trying to achieve. But you should follow #Arvind's answer:
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.TimeZone;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
String formattedDate = sdf.format(new Date());
// Updated the lines below
LocalDateTime localDateTime = LocalDateTime.parse(formattedDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Date date = Date.from(localDateTime.atZone(ZoneId.of("America/Chicago")).toInstant());
Best is if you can skip the Date class completely and in your response use Instant or ZonedDateTime from java.time, the modern Java date and time API.
If you cannot avoid using the outdated Date class
… I was wondering if there was a more simple way to make a Date object
that would match the format of #JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "America/Chicago")
Essential edit: It depends very much on what you mean by match the format. A Date can neither have a format nor a time zone. The string in your JSON has got the format mentioned. The Date has not since this would no be possible. The time zone, America/Chicago, is not present neither in JSON nor in the Date. It is only used for converting between the two. Two Date objects are equal if they denote the same point in time, there is nothing more to it. When you ask about formatting the Date to match the #JsonFormat, this necessarily means formatting into a string.
To convert a string like 2021-08-20 14:23:44 into an old-fashioned Date object I would first define the format and time zone statically:
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ROOT);
private static final ZoneId ZONE = ZoneId.of("America/Chicago");
And then do:
String responseDateString = "2021-08-20 14:23:44";
Instant inst = LocalDateTime.parse(responseDateString, FORMATTER)
.atZone(ZONE)
.toInstant();
Date oldfashionedDate = Date.from(inst);
System.out.println(oldfashionedDate);
Output in my time zone is:
Fri Aug 20 21:23:44 CEST 2021
If I set my time zone to America/Chicago before running, it’s easier to see that the result is correct:
Fri Aug 20 14:23:44 CDT 2021
What went wrong in your code?
First you are correct that formatting a Date into a string only to parse it back is over-complicating things. Second you noticed that your exception came from this line:
LocalDate localDate = LocalDate.parse(formattedDate);
A LocalDate is a date without time of day. So its one-arg parse method expects only 2021-08-20 in the string, nothing more. It was complaining about the space, not because it was a space but just because there were more characters after the expected ones at all.

How to convert a given time (String) to a LocalTime?

I will be asking a user to enter a specific time: 10AM, 12:30PM, 2:47PM, 1:09AM, 5PM, etc.
I will be using a Scanner to get the user's input.
How can I parse/convert that String to a LocalTime object? Is there any built-in function in Java that will allow me to do that?
Just use a java.time.format.DateTimeFormatter:
DateTimeFormatter parser = DateTimeFormatter.ofPattern("h[:mm]a");
LocalTime localTime = LocalTime.parse("10AM", parser);
Explaining the pattern:
h: am/pm hour of day (from 1 to 12), with 1 or 2 digits
[]: delimiters for optional section (everything inside it is optional)
:mm: a : character followed by minutes with 2 digits
a: designator for AM/PM
This works for all your inputs.
If you want to parse time only, you should try parsing to LocalTime. Following is the code to implement this:
DateTimeFormatter parseFormat = new DateTimeFormatterBuilder().appendPattern("hh[:mm]a").toFormatter();
LocalTime localTime = LocalTime.parse(timeValue, parseFormat);
The solution provided in the accepted answer works only if you execute it on a machine with ENGLISH as the default Locale; it will fail otherwise.
Never use SimpleDateFormat or DateTimeFormatter without a Locale because they are Locale-sensitive. Use the following one to avoid failure due to the default Locale not matching the input.
DateTimeFormatter.ofPattern("h[:mm]a", Locale.ENGLISH);
Demo:
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.stream.Stream;
public class Main {
public static void main(String args[]) {
DateTimeFormatter parser = DateTimeFormatter.ofPattern("h[:mm]a", Locale.ENGLISH);
Stream.of(
"10AM",
"12:30PM",
"2:47PM",
"1:09AM",
"5PM"
)
.map(s -> LocalTime.parse(s, parser))
.forEach(System.out::println);
// See how it can fail with other locales
// Assuming the default Locale of the system is Locale.CHINA,
// DateTimeFormatter.ofPattern("h[:mm]a") will automatically be turned into
// DateTimeFormatter.ofPattern("h[:mm]a", Locale.CHINA) causig the parsing to
// fail
DateTimeFormatter errorProneParser = DateTimeFormatter.ofPattern("h[:mm]a", Locale.CHINA);
LocalTime localTime = LocalTime.parse("10AM", errorProneParser);
}
}
Output:
10:00
12:30
14:47
01:09
17:00
Exception in thread "main" java.time.format.DateTimeParseException: Text '10AM' could not be parsed at index 2
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2052)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1954)
at java.base/java.time.LocalTime.parse(LocalTime.java:465)
at Main.main(Main.java:24)
Hope this will help you. I think you could do it using DateTimeFormatter and LocalDateTime parsing like below example.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE, MMM d, yyyy HH:mm:ss a");
String date = "Tuesday, Aug 13, 2017 12:10:56 PM";
LocalDateTime localDateTime = LocalDateTime.parse(date, formatter);
System.out.println(localDateTime);
System.out.println(formatter.format(localDateTime));
Output
2017-08-13T12:10:56
Tuesday, Aug 13, 2017 12:10:56 PM
Similar posts would be Java 8 - Trying to convert String to LocalDateTime

Unable to obtain LocalDateTime from TemporalAccessor when parsing LocalDateTime (Java 8)

I am simply trying to convert a date string into a DateTime object in Java 8. Upon running the following lines:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime dt = LocalDateTime.parse("20140218", formatter);
I get the following error:
Exception in thread "main" java.time.format.DateTimeParseException:
Text '20140218' could not be parsed:
Unable to obtain LocalDateTime from TemporalAccessor:
{},ISO resolved to 2014-02-18 of type java.time.format.Parsed
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1918)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1853)
at java.time.LocalDateTime.parse(LocalDateTime.java:492)
The syntax is identical to what has been suggested here, yet I am served with an exception. I am using JDK-8u25.
It turns out Java does not accept a bare Date value as DateTime. Using LocalDate instead of LocalDateTime solves the issue:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate dt = LocalDate.parse("20140218", formatter);
If you really need to transform a date to a LocalDateTime object, you could use the LocalDate.atStartOfDay(). This will give you a LocalDateTime object at the specified date, having the hour, minute and second fields set to 0:
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime time = LocalDate.parse("20140218", formatter).atStartOfDay();
For what is worth if anyone should read again this topic(like me) the correct answer would be in DateTimeFormatter definition, e.g.:
private static DateTimeFormatter DATE_FORMAT =
new DateTimeFormatterBuilder().appendPattern("dd/MM/yyyy[ [HH][:mm][:ss][.SSS]]")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.toFormatter();
One should set the optional fields if they will appear. And the rest of code should be exactly the same.
Edit : usefull thing from wittyameta comment :
Remember to add the parseDefaulting AFTER you have called appendPattern. Otherwise it'll give DateTimeParseException
For anyone who landed here with this error, like I did:
Unable to obtain LocalDateTime from TemporalAccessor: {HourOfAmPm=0, MinuteOfHour=0}
It came from a the following line:
LocalDateTime.parse(date, DateTimeFormatter.ofPattern("M/d/yy h:mm"));
It turned out that it was because I was using a 12hr Hour pattern on a 0 hour, instead of a 24hr pattern.
Changing the hour to 24hr pattern by using a capital H fixes it:
LocalDateTime.parse(date, DateTimeFormatter.ofPattern("M/d/yy H:mm"));
This is a really unclear and unhelpful error message. After much trial and error I found that LocalDateTime will give the above error if you do not attempt to parse a time. By using LocalDate instead, it works without erroring.
This is poorly documented and the related exception is very unhelpful.
Expanding on retrography's answer..: I had this same problem even when using LocalDate and not LocalDateTime. The issue was that I had created my DateTimeFormatter using .withResolverStyle(ResolverStyle.STRICT);, so I had to use date pattern uuuuMMdd instead of yyyyMMdd (i.e. "year" instead of "year-of-era")!
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseStrict()
.appendPattern("uuuuMMdd")
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT);
LocalDate dt = LocalDate.parse("20140218", formatter);
(This solution was originally a comment to retrography's answer, but I was encouraged to post it as a stand-alone answer because it apparently works really well for many people.)
If the date String does not include any value for hours, minutes and etc you cannot directly convert this to a LocalDateTime. You can only convert it to a LocalDate, because the string only represent the year,month and date components it would be the correct thing to do.
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate ld = LocalDate.parse("20180306", dtf); // 2018-03-06
Anyway you can convert this to LocalDateTime.
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate ld = LocalDate.parse("20180306", dtf);
LocalDateTime ldt = LocalDateTime.of(ld, LocalTime.of(0,0)); // 2018-03-06T00:00
You do not need to define a DateTimeFormatter
You do not need to define a DateTimeFormatter to parse the given date string. You can use the OOTB (Out-Of-The-Box), DateTimeFormatter.BASIC_ISO_DATE to parse it.
Demo:
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
LocalDate date = LocalDate.parse("20140218", DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(date);
// In case you need an instance of LocalDateTime
LocalDateTime ldt = date.atTime(LocalTime.MIN);
System.out.println(ldt);
}
}
Output:
2014-02-18
2014-02-18T00:00
ONLINE DEMO
Learn more about the modern Date-Time API* from Trail: Date Time.
* 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. Note that Android 8.0 Oreo already provides support for java.time. Check this answer and this answer to learn how to use java.time API with JDBC.
DateTimeFormatter format = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
.toFormatter();
Works for me
In cases where you simply want to take a format (whether or not it has time) and want to parse to a LocalDateTime, you can do the following.
LocalDateTime parseDateTime(String dateTime, DateTimeFormatter fmt) {
return fmt.parse(dateTime, t -> {
LocalDate date = t.query(TemporalQueries.localDate());
LocalTime time = t.query(TemporalQueries.localTime());
return LocalDateTime.of(date, time != null ? time : LocalTime.MIDNIGHT);
});
}
I needed this because I was getting the date/time pattern as a parameter for a custom Spark UDF.
This works fine
public class DateDemo {
public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy hh:mm");
String date = "16-08-2018 12:10";
LocalDate localDate = LocalDate.parse(date, formatter);
System.out.println("VALUE="+localDate);
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm");
LocalDateTime parse = LocalDateTime.parse(date, formatter1);
System.out.println("VALUE1="+parse);
}
}
output:
VALUE=2018-08-16
VALUE1=2018-08-16T12:10
Try this one:
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM-dd-yyyy");
LocalDate fromLocalDate = LocalDate.parse(fromdstrong textate, dateTimeFormatter);
You can add any format you want. That works for me!
I arrived at this problem because my input string didn't have a year in it:
input string: Tuesday, June 8 at 10:00 PM
formatter: DateTimeFormatter.ofPattern("EEEE, MMMM d 'at' h:mm a", Locale.US);
I knew the year so I just appended it to get:
input string: Tuesday, June 8 at 6:30 PM 2021
formatter: DateTimeFormatter.ofPattern("EEEE, MMMM d 'at' h:mm a uuuu", Locale.US);

Problem while fetching milliseconds from Date

I have a date in string format as 25 November 2010 and I am trying to fetch the milliseconds of that date, for that I have written the below code:
strDateSelcted = "25 November 2010" // Actually I am receiving date in this format
SimpleDateFormat curFormater = new SimpleDateFormat("dd MMM yyyy");
try {
Date dateObj = curFormater.parse(strDateSelcted);
insertEventtoCalendar(dateObj.getTime()); // Actually insert an event onto the native calendar
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
But, when I try to run the application,it creates an event a day before the date inserted, i.e. For 25 November 2010 it inserts event on 24 November 2010 and For 27 November 2010 it inserts event on 26 November 2010, and same.
Where am I making a mistake?
To set the timezone used by the date formatter: call the setTimeZone method
e.g.
curFormater.setTimeZone(TimeZone.getTimeZone("UTC"));
For one, your date pattern is wrong, use dd MMMM yyyy. MMM parses & returns Nov (not November).
Also, since there is no millisecond provided in your date string, the millisecond will be set to 0.
Seeing that Jon Skeet updated me with the question, it might be timezone issue (as he mentioned). Sorry for the misunderstanding.
Test code:
/**
*
*/
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* #author The Elite Gentleman
*
*/
public class Test {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
String date = "25 November 2010";
SimpleDateFormat sdf = new SimpleDateFormat("dd MMMM yyyy");
Date d = sdf.parse(date);
System.out.println(d.getTime());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Value: 1290636000000
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*.
Note that a Date-Time without a timezone represents a local Date-Time which may be different for a different timezone e.g. today, it is 31st May 2021 in my timezone, Europe/London whereas 1st June 2021 in Australia/Sydney. So, in order to represent a moment (i.e. an instantaneous point on the timeline in UTC), Java provides a class called Instant which you can convert to other Date-Time types e.g.
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
public class Main {
public static void main(String[] args) {
Instant now = Instant.now();
LocalDate todayUK = now.atZone(ZoneId.of("Europe/London")).toLocalDate();
LocalDate todaySydney = now.atZone(ZoneId.of("Australia/Sydney")).toLocalDate();
System.out.println(todayUK);
System.out.println(todaySydney);
LocalDateTime nowUK = now.atZone(ZoneId.of("Europe/London")).toLocalDateTime();
LocalDateTime nowSydney = now.atZone(ZoneId.of("Australia/Sydney")).toLocalDateTime();
System.out.println(nowUK);
System.out.println(nowSydney);
}
}
Output:
2021-05-31
2021-06-01
2021-05-31T16:22:40.418214
2021-06-01T01:22:40.418214
So, you need to choose a timezone. Most digital operations are based on the UTC (timezone offset, +00:00 hours).
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("d MMMM u", Locale.ENGLISH);
LocalDate date = LocalDate.parse("25 November 2010", dtf);
ZonedDateTime zdt = date.atStartOfDay(ZoneOffset.UTC);
Instant instant = zdt.toInstant();
System.out.println(instant);
long millis = instant.toEpochMilli();
System.out.println("Milliseconds since January 1, 1970, 00:00:00 GMT: " + millis);
}
}
Output:
2010-11-25T00:00:00Z
Milliseconds since January 1, 1970, 00:00:00 GMT: 1290643200000
The Z in the sample output is the timezone designator for a zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).
Now, pass millis to your insertEventtoCalendar:
insertEventtoCalendar(millis);
Note: For any reason you need an object of java.util.Date, you can get it from this Instant as
Date date = Date.from(instant);
Learn more about java.time, the modern Date-Time API* from Trail: Date Time.
What went wrong with your code?
You tried parsing the date string without setting a timezone and therefore, SimpleDateFormat used your JVM's timezone to parse the date string, giving you a moment/instant corresponding to the start-of-the-day on 25 November 2010 in your timezone. To fix the problem, set the desired Timezone (e.g. UTC) to the SimpleDateFormat instance before parsing i.e.
SimpleDateFormat curFormater = new SimpleDateFormat("dd MMMM yyyy", Locale.ENGLISH);
curFormater.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
Two more important notes:
Use MMMM instead of MMM for the full monthname.
Never use SimpleDateFormat or DateTimeFormatter without a Locale.
* 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.
It's almost certainly a time zone issue. Check which time zone your SimpleDateFormat is using, and the one your phone is using to display the event.
For diagnostic purposes I suggest you log the result of dateObj.getTime() and you can check exactly what that means on a desktop machine.
Use Locale.getDefault() when Your using SimpleDateFormat.I hope it may solve your problem.

Categories

Resources