I cannot see why this code is failing:
#Test
public void test() {
final SimpleDateFormat sdf= new SimpleDateFormat("yyyyMMddHHmm");
try {
sdf.setLenient(false);
Date d = sdf.parse("202003290230");
} catch (ParseException e){
e.printStackTrace();
}
}
I get the exception java.text.ParseException: Unparseable date.
If I set sdf.setLenient(true) then it works, but the time in the object Date returned is '03:30' and not '02:30'.
Can someone explain me what's going on in here? Thanks.
As OH GOD SPIDERS noted in a comment your real problem is that that time doesn’t exist in you default time zone because of the spring forward, the transition to summer time (DST).
java.time
I recommend that you use java.time, the modern Java date and time API, for your date and time work. The short-sighted answer is: use LocalDateTime from java.time.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmm");
String dateTimeString = "202003290230";
LocalDateTime ldt = LocalDateTime.parse(dateTimeString, formatter);
System.out.println(ldt);
Output is:
2020-03-29T02:30
A LocalDateTime is a date and time without time zone. So it doesn’t discover that the time doesn’t exist in your time zone. The result is 2:30 as in the string.
Detecting a non-existing time
It seems you’re in a Central European time zone or some other time zone where summer time began on the last Sunday in March, and the clocks were turned forward from 2 to 3 (AM). So there was no 2:30. Supposing that you want to know, you may do:
ZoneId zone = ZoneId.of("Europe/Paris");
ZonedDateTime zdt = ldt.atZone(zone);
if (zdt.toLocalDateTime().equals(ldt)) {
System.out.println("The time " + zdt + " exists");
} else {
System.out.println("The time " + ldt + " does not exist in " + zone);
}
The time 2020-03-29T02:30 does not exist in Europe/Paris
java.time too gives you 3:30 instead of 2:30 when given a time in the spring gap. So when converting back from ZonedDateTime to LocalDateTime in this case we don’t get the same time again, which we use for detecting the non-existing time.
I further recommend that you use ZonedDateTime for past dates and times, not LocalDateTime.
Java 6?
This project is made with Java6 and the company doesn't want to update
it, …
java.time has been backported, and I have tested the code above with the backport, ThreeTen Backport, see the link at the bottom.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310). I’m unsure whether the very latest release of ThreeTen Backport works with Java 6 or only with Java 7(+). If this is an issue, go back a few releases and find one that works with Java 6 too.
On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.
Don’t use SimpleDateFormat
The date and time classes you were trying to use, Date and SimpleDateFormat, are poorly designed and long outdated. In your case they showed a behaviour that depends on a time zone that isn’t present in the code at all, which is quite confusing. I recommend that you don’t use those classes.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
Java 8+ APIs available through desugaring
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Related
I am trying to convert time zone, but it's adding one day extra from java function.
"" deActivationDate=2021-06-25T23:59:59.000+0000"";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
try {
Date date =formatter.parse(deActivationDate);
deActivationDate=formatter.format(date);
LOGGER.info("time format printing 1" +deActivationDate);//2021-06-26T04:29:59.000+0430
deActivationDate = deActivationDate.substring(0, deActivationDate.length()-2)+":30";
LOGGER.info("time format printing 2" +deActivationDate);//2021-06-26T04:29:59.000+04:30""
In above deactivation date is 25 when I am giving input but after formater parase method its converting as 26 why one day os getting add how to avoid it.
java.time through ThreeTen Backport
You should seriously consider using java.time, the modern Java date and time API, for your non-trivial date and time work.
It’s not very clear from your question, but I think that you want to convert the date and time string to the same date and wall-clock time in your own time zone, in this case, Asia/Tehran time zone. So a different point in time: near the end of the day in Iran rather than near the end of the day in UTC. And with a colon in the UTC offset.
I am declaring two formatters, one for parsing without colon and one for formatting back with colon:
private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendPattern("xx")
.toFormatter();
private static final DateTimeFormatter PRINTER = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendPattern("xxx")
.toFormatter();
Now your conversion goes like this:
String deActivationDate = "2021-06-25T23:59:59.000+0000";
OffsetDateTime dateTime = OffsetDateTime.parse(deActivationDate, PARSER);
deActivationDate = dateTime.atZoneSimilarLocal(ZoneId.systemDefault())
.format(PRINTER);
System.out.println("time format printing: " +deActivationDate);
Output is — tested on Java 1.7.0_67 with ThreeTen Backport version 1.3.6:
time format printing: 2021-06-25T23:59:59+04:30
Java knows that Asia/Tehran time zone uses summer time (DST) on June 25, so converts to and prints your desired offset of +04:30. Had the date been in the standard time part of the year, +03:30 would have been printed instead.
The 0 milliseconds are not printed, which for most purposes is an advantage. The format is ISO 8601, and according to the ISO 8601 standard the fraction of second is optional when it is 0. If you require the millis to be there, use this simpler formatter instead:
private static final DateTimeFormatter PRINTER
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxxx");
time format printing: 2021-06-25T23:59:59.000+04:30
Half-open: You should not represent the end of the day by 1 second before the start of the new day. First, it’s wrong: the day does not end a second before it ends. Second, it may give rise to errors because of times that fall within that last second and therefore in your program will neither belong to one day or the other. Even if this does not happen in practice, you will have programmers wasting their time wondering whether it may happen. Instead represent the end of the day as the first moment of the following day exclusive (typically 00:00). When testing, require a time to be strictly before the end of the day to belong to the day. This approach is standard for all kinds of intervals and certainly for time intervals. They are then known as half-open intervals.
Question: Doesn’t java.time require Java 8?
java.time works nicely on Java 7. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
Java 8+ APIs available through desugaring
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Wikipedia article: ISO 8601
Here's the fix for your code. Though we recommend not to do it via substring method.
String deActivationDate="2021-06-25T23:59:59.000+0000";
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date =formatter.parse(deActivationDate);
deActivationDate=formatter.format(date);
System.out.println("time format printing 1: " +deActivationDate);
//2021-06-25T23:59:59.000+0000
deActivationDate = deActivationDate.substring(0,
deActivationDate.length()-4)+"0430";
System.out.println("time format printing 2: " +deActivationDate);
//2021-06-25T23:59:59.000+0430
} catch (Exception e) {
System.err.println(e.getMessage());
}
Thanks to all for your suggestion #beshambher-chaukhwan m i have achieved changes with below code
String deActivationDate="2021-06-25T23:59:59.000+0000";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
try {
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date =formatter.parse(deActivationDate);
deActivationDate=formatter.format(date);
if(TimeZone.getDefault().useDaylightTime()) {
deActivationDate = deActivationDate.substring(0, deActivationDate.length()-4)+"04:30";
}else {
deActivationDate = deActivationDate.substring(0, deActivationDate.length()-4)+"03:30";
}
I had two edit text for user to enter time (24 hours format).
How could i get those times from Edittext and deduct 5 hours and 30 minutes from user selected time.
Reason for deducting time : Converting IST to UTC timezone.
My final output should be like - HH:MM:SS:Milleseconds (Ex : 18:25:30:245635).
Thanks in advance.
java.time
ZoneId zone = ZoneId.of("Asia/Kolkata");
String timeString = "18:25:30.245635";
LocalTime time = LocalTime.parse(timeString);
LocalTime utcTime = LocalDate.now(zone) // Today
.atTime(time) // Today at the time in question
.atZone(zone) // Date and time in IST
.toOffsetDateTime() // Convert to OffsetDateTime for the next step
.withOffsetSameInstant(ZoneOffset.UTC) // Convert to UTC
.toLocalTime(); // Extract only the time of day
System.out.println("UTC time: " + utcTime);
Output is:
UTC time: 12:55:30.245635
I have assumed today’s date. Please check if this assumption is right for you. While the UTC offset for Asia/Kolkata hasn’t changed much recently, other time zones change their offset twice a year.
I changed your time format to have a period (point) rather than a colon between the seconds and fraction of second as is customary. If you do require a colon there, you need a DateTimeFormatter for parsing.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Wikipedia article: ISO 8601
I am trying to make an application which takes start date, start time and end time. If the end time does not lie in the start date then how I can calculate the ending date based on the end time.
Here is the screenshot of what I want
As you can see in the picture when you enter start date, start time and end time, the end time is ending on the next date, it is automatically calculating the end date. (I also underlined it.)
How I can achieve this things? What the logic behind.
java.time
ZoneId zone = ZoneId.of("America/Chicago");
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("h:mm a (OOOO)", Locale.US);
LocalDate startDate = LocalDate.of(2019, Month.SEPTEMBER, 18);
LocalTime startTime = LocalTime.of(14, 0);
LocalTime endTime = LocalTime.of(4, 0);
ZonedDateTime start = ZonedDateTime.of(startDate, startTime, zone);
ZonedDateTime end = ZonedDateTime.of(startDate, endTime, zone);
if (end.isBefore(start)) {
end = ZonedDateTime.of(startDate.plusDays(1), endTime, zone);
}
System.out.println("Date: " + startDate);
System.out.println("Start Time: " + start.format(timeFormatter));
System.out.println("End Time: " + end.format(timeFormatter));
System.out.println("Ends on " + end.toLocalDate());
Output from this snippet is:
Date: 2019-09-18
Start Time: 2:00 PM (GMT-05:00)
End Time: 4:00 AM (GMT-05:00)
Ends on 2019-09-19
I have shown you how to use a DateTimeFormatter for formatting the times. You will probably want to use formatters for the dates too.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
I get the datetime content in the below string format with offset time value from the source system.
2019-02-16T10:00:00+08:00
Where i want to convert that into local date time using the offset value.I tried the below, but not getting the expected result.
DateTime date = new DateTime("2019-02-16T10:00:00+08:00");
-->output == 2019-02-16T02:00:00.000Z (the hour is decreased instead of increasing)
DateTime date = new DateTime("2019-02-16T10:00:00-08:00");
-->output == 2019-02-16T18:00:00.000Z (the hour is increased instead of decreasing).
is there any simple way to the expected output?
Note: I am using Java 1.7
What you are doing is correct. To get the time in your local time zone:
DateTime date = new DateTime("2019-02-16T10:00:00+08:00");
DateTime dateTimeInLocalTimeZone = date.withZone(DateTimeZone.getDefault());
System.out.println(dateTimeInLocalTimeZone);
On my computer in Europe/Copenhagen time zone I got
2019-02-16T03:00:00.000+01:00
As has been said in the comments, +08:00 is the offset that has already been added compared to UTC time. So your string denoted the same point in time as 2019-02-16T02:00:00+00:00. It may also be written as 2019-02-16T02:00:00Z since Z (pronounced “Zulu”) means UTC.
java.time and ThreeTen Backport
If you are not already tied to Joda-Time, you may prefer to use java.time, the modern Java date and time API. The code is similar:
OffsetDateTime sourceDateTime = OffsetDateTime.parse("2019-02-16T10:00:00+08:00");
ZonedDateTime dateTimeInLocalTimeZone = sourceDateTime.atZoneSameInstant(ZoneId.systemDefault());
2019-02-16T03:00+01:00[Europe/Copenhagen]
Question: Can I use java.time on Java 1.7?
Note: I am using Java 1.7
No big problem, java.time just requires at least Java 6. I have run the above code on jdk1.7.0_79.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Another way to do that :
String dt = "2019-02-16T10:00:00+08:00";
ZonedDateTime zd = ZonedDateTime.parse("2019-02-16T10:00:00+08:00");
System.out.println(zd.toLocalDateTime().plusSeconds(zd.getOffset().getTotalSeconds()));
Output
2019-02-16T18:00
In Android...I am expecting 3:12 pm as time out put of the following code but I get 4:12 pm. Whats the correct way to parse this date time format.
String dt = "2018-09-02T19:12:00-0400";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
try {
Date date = dateFormat.parse(dt);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
Time zone
It’s best to specify explicitly in which time zone you want your output:
DateTimeFormatter inputFormatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXX");
DateTimeFormatter displayFormatter = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.LONG)
.withLocale(Locale.ENGLISH);
ZoneId displayZone = ZoneId.of("Pacific/Pitcairn");
String dt = "2018-09-02T19:12:00-0400";
OffsetDateTime dateTime = OffsetDateTime.parse(dt, inputFormatter);
String displayDateTime = dateTime.atZoneSameInstant(displayZone)
.format(displayFormatter);
System.out.println(displayDateTime);
This prints:
September 2, 2018 at 3:12:00 PM PST
I have used Pacific/Pitcairn time zone in my code, but you know better which time zone you want.
I am also using java.time, the modern Java date and time API. The date-time classes you are using, SimpleDateFormat and Date, are considered long outdated, and java.time is so much nicer to work with.
What went wrong in your code?
Your way of parsing your date string is correct and produces the correct Date.
When printing the Date, you are implicitly calling toString. The outdated Date class has a peculiar and confusing toString method: it grabs the JVM’s time zone setting and uses it for producing the string. So depending on your default time zone, you can get any hour of day in the output. So it seems your JVM’s time zone setting didn’t correspond to what you had expected.
Since you expected 3:12 PM from your input of 19:12:00-0400, I take it that you want a time zone that is at offset -08:00 from UTC in September. If for example your default time zone was America/Los_Angeles, the standard time of which is at -08:00, you would get Sun Sep 02 16:12:00 PDT 2018 because summer time (daylight saving time) is in effect in California in September, so the offset is -07:00.
Relying on your JVM’s default time zone is always fragile since the setting may be changed at any time by other parts of your program or by other programs running in the same JVM.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.