I have certain date field of a record in sqlite database that is saved at certain format.
To convert this date column to a certain format, I did some date formatting and add it in an array dbDates with the following code-
SimpleDateFormat dateIn = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
dbDates.add(dateIn.format(formatter.parse("2013-12-16T02:00:00.000Z");
dbDates.add(dateIn.format(formatter.parse("2013-12-15T01:30:00.000Z");
The dbDates as printed in console is now in the following format -
Mon Dec 16 02:00:00 GMT+05:30 2013
Sun Dec 15 01:30:00 GMT+05:30 2013
NOTE: As noticed, +05:30 is added at the end of each dbDate.
This caused a problem when I convert it to user timezone.
So adding this line ----
dateIn.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
Changes the output to -
Sun Dec 15 12:30:00 PST 2013
Sun Dec 14 12:00:00 PST 2013
However, the correct output should be:
Sun Dec 15 18:00:00 PST 2013
Sun Dec 14 17:30:00 PST 2013
So, there is +05:30 difference in the output. How to resolve that ?
The java.util.Date class bundled with Java has no time zone defined inside the instance. Yet its toString method renders a string using the JVM's default time zone. I'll bet your JVM is set to an Indian time zone, given to +05:30.
This is one of many reasons to avoid using the java.util.Date/Calendar classes. They are notoriously bad in both design and implementation.
Immediately download for yourself a copy of the Joda-Time library. Use that for all your business logic and calculations.
In Joda-Time, a DateTime instance does indeed know its own time zone.
When necessary to deal with other classes, convert to a j.u.Date by calling the toDate method on a DateTime instance.
Search StackOverflow.com for joda to find many examples.
In Java 8, either continue using Joda-Time or switch to the new java.time.* classes defined by JSR 310. The new classes are inspired by Joda-Time but are entirely re-architected.
Related
I need the current date in following format at 00:00:00 CST time.
Like say current date is July 9 2021 Then I need that date along with 00:00:00 time.
Expected Output:
Fri Jul 09 00:00:00 CST 2021
Current code:
LocalDateTime date= LocalDateTime.now().with(LocalTime.MIN);
Date dayStart= Date.from(date.atZone(ZoneId.systemDefault()).toInstant());
Output of CurrentCode: Fri Jul 09 00:00:00 UTC 2021
Current code picking servertime /GMT which is 5hrs ahead of CST.
Example: 09AM GMT is 14 CST/2PM CST
I have tried to set calendar to 00:00:00 and setTimeZone to America/New_York. But while am returning output as calendar.getTime() give some other time rather than giving CST 00:00:00.
Tried : #scheduled(zone="America/New_york" ) --Not Working.
There are two good answers. My suggestion only differs in the detail (which is where the devil is, according to some).
First of all you should avoid using the Date class if you can. You are already using java.time, the modern Java date and time API, (LocalDateTime, LocalTime, ZoneId). You are getting all the functionality that you need from java.time. So I am assuming that you are only converting to Date because you need a Date for some legacy API that you cannot afford to upgrade to java.time just now.
Instant startOfDay = ZonedDateTime.now(ZoneId.systemDefault())
.truncatedTo(ChronoUnit.DAYS)
.toInstant();
Date oldfashionedDate = Date.from(startOfDay);
System.out.println(oldfashionedDate);
.truncatedTo(ChronoUnit.DAYS) throws away the time part of the ZonedDateTime, usually leaving us with 00:00:00 on the same day in the same time zone.
Edit:
I want America Chicago time CDT
Running the above code with the default time zone of the JVM set to America/Chicago gave:
Mon Jul 12 00:00:00 CDT 2021
Getting the right Date value and getting the expected printed output are two different things since Date.toString() picks the default time zone of the JVM and uses it for rendering the string to be returned. This behaviour may give surprises. There is no way to persuade Date.toString() to use a different time zone, so the above output only comes through setting the default time zone.
Original text: There are a lot of time zones referred to as CST and there’s no way I can be sure which one you intended (and i believe that the comments stating that America/New_York is not one of them are correct). However, the only one that I could persuade the old-fashioned Date class to abbreviate CST was China Standard Time. Running the above code in Asia/Shanghai time zone gave this output:
Sat Jul 10 00:00:00 CST 2021
It looks right to me. Since you asked your question it has become Saturday 10th in China Standard Time time zone.
Any time zone will work for getting the right Date value, the start of the day in that time zone. You also wanted an abbreviation of CST in the printed output. Time zones that did not work for this include:
Australia/Adelaide time zone. Output was Sat Jul 10 00:00:00 ACST 2021. So even though Australian Central Standard Time is sometimes abbreviated just CST, Date chose ACST.
America/Havana. Cuba uses Cuba Daylight Time at this time of year, so CDT is output.
America/Winnipeg and American/Chicago. North American Central Time uses daylight saving time too, so here too CDT is output.
In any case, you know which time zone you intended, so I am leaving to you to pick.
The easiest way to change the timezone is to use System.setProperty("user.timezone", "America/New_York"); in Java NOTE:: America/New_York is not CST
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
class DateAndTimeZoneFormatter {
public static void main(String[] args) {
System.setProperty("user.timezone", "America/New_York");
LocalDateTime date = LocalDateTime.now().with(LocalTime.MIN);
Date dayStart = Date.from(date.atZone(ZoneId.systemDefault()).toInstant());
System.out.println(dayStart);
}
}
You could try to use a ZonedDateTime with a specific ZoneId:
public static void main(String[] args) {
// define the zone to be used
ZoneId americaChicago = ZoneId.of("America/Chicago");
// then take the date of today
ZonedDateTime nowInChicago = ZonedDateTime.of(
LocalDate.now(), // today
LocalTime.MIN, // start of day
americaChicago // zone
);
// define an output format
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendPattern("EEE MMM dd HH:mm:ss")
.appendLiteral(' ')
.appendZoneText(TextStyle.SHORT)
.appendLiteral(' ')
.appendPattern("uuuu")
.toFormatter(Locale.ENGLISH);
// then print the formatted String representation
System.out.println(nowInChicago.format(dtf));
}
This outputs
Fri Jul 09 00:00:00 CDT 2021
Downsides:
this won't fully match your expected output due to CST not being applied because it is daylight saving time. Therefore, CDT will be the output.
taking a Date.from this ZonedDateTime.toInstant() will affect the values:
Applying these two lines
Date sameNowInChicago = Date.from(nowInChicago.toInstant());
System.out.println(sameNowInChicago);
will output
Fri Jul 09 07:00:00 CEST 2021
on my machine because it is configured to have a ZoneId.of("Europe/Berlin"), which will be taken into account when printing a java.util.Date.
CEST ⇒ Central European Summer Time.
I have a Spring application and i receive a date from an angular client as a String, how can i convert this date to a Java Date, following is the TypeScript Date format :
TypeScript Date Format : Mon Jan 04 2021 00:00:00 GMT+0100 (Central European Standard Time)
Java Date Format : Mon Jan 04 00:00:00 CET 2021
java.time
how can i convert this date to a Java Date, following is the
TypeScript Date format :
TypeScript Date Format : Mon Jan 04 2021 00:00:00 GMT+0100 (Central European Standard Time)
java.time provides you with DateTimeFormatterBuilder using which you can define a complex format for parsing/formatting as shown below:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.TextStyle;
import java.util.HashSet;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "Mon Jan 04 2021 00:00:00 GMT+0100 (Central European Standard Time)";
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("EEE MMM dd uuuu HH:mm:ss")
.appendLiteral(" ")
.appendZoneRegionId()
.appendOffset("+HHmm", "Z")
.appendLiteral(" (")
.appendZoneText(TextStyle.FULL)
.appendLiteral(")")
.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
}
}
Output:
2021-01-04T00:00+01:00[Europe/Paris]
Java Date Format : Mon Jan 04 00:00:00 CET 2021
A date-time object is supposed to store the information about the date, time, timezone etc., not about the formatting. You can format a date-time object into a String object with the pattern of your choice using date-time formatting API.
The date-time formatting API for the modern date-time types is in the package, java.time.format e.g. java.time.format.DateTimeFormatter, java.time.format.DateTimeFormatterBuilder etc.
The date-time formatting API for the legacy date-time types is in the package, java.text e.g. java.text.SimpleDateFormat, java.text.DateFormat etc.
Given below is how you can format zdt (obtained above) into a custom format:
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z uuuu", Locale.ENGLISH);
String strDateTimeFormatted = zdt.format(dtfOutput);
System.out.println(strDateTimeFormatted);
Output:
Mon Jan 04 00:00:00 CET 2021
Learn about the modern date-time API from Trail: Date Time.
In case you want to convert zdt (obtained above) into java.util.Date, you can do so as shown below:
Date date = Date.from(zdt.toInstant());
System.out.println(date);
A note about the legacy date-time API:
The java.util.Date object is not a real date-time object like the modern date-time types; rather, it represents the milliseconds from the Epoch of January 1, 1970. When you print an object of java.util.Date, its toString method returns the date-time calculated from this milliseconds value. Since java.util.Date does not have timezone information, it applies the timezone of your JVM and displays the same. If you need to print the date-time in a different timezone, you will need to set the timezone to SimpleDateFomrat and obtain the formatted string from it.
3. The date-time API of java.util 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.
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.
Mon Jan 04 2021 00:00:00 GMT+0100 (Central European Standard Time)
This is an ambiguous timestamp. Political entities and the world at large is free to redefine what CEST means, at which point GMT+0100 means one thing, and CST means another. Furthermore, CEST has implications for any 'math' done on this date that are different from GMT+0100.
For example, if I want to know the date 6 months from that one, then if CST is leading, you'd want:
Thu Jul 04 2021 00:00:00 GMT+0200 (Central European Daylight Time)
or possibly you'd want that time but one hour earlier - another open question, there is no clear answer to that question inherent in the idea 'add 6 months to this timestamp', so you will have to specify it, because otherwise you get some random guess by the system, and you almost never want your computer / programming language to guess at a 50/50 concept like this.
If GMT+0100 is leading, you end up with:
Thu Jul 04 2021 00:00:00 GMT+0100 (Central European Standard Time)
Which is completely bizarre there are zero places on the entire planet where this timestamp makes sense as printed: Nobody is on CEST on the 4th of july, anywhere. It's a timestamp that is 'real', and yet used by literally 0 people.
Thus, before continuing, first you need to ask yourself which bits and bobs from what you do have, you want to preserve when you convert it. Note that there are 3 different ideas of time:
'solarflares' time: Commonly measured as millis-since-epoch. This is devoid of human concepts such as timezones. To record the exact instant in time that an event happened, or will happen, if the event is not a human appointment (i.e. when a solarflare is predicted to happen or did happen, hence the name 'solarflares' time). In java, best represented by java.time.Instant.
'appointment' time: Commonly measured as a big sack of numbers: A year, a month, a day, hour, minute, second, and a timezone. And not one of those GMT+0100 useless zones, but something like Europe/Amsterdam. Something like Central European Standard Time is somewhat common, but also a very bad idea. These names have no clear meaning, something like Europe/Amsterdam is designed to most likely always have clear meaning, that's a proper zone. The idea is: Let's say you make an appointment with your dentist, in Amsterdam, for next month. It sure seems like a solarflares kind of deal, but it is not: if the netherlands decides to join a different timezone, the absolute # of seconds until your appointment changes along. Whereas that solarflare is not going to occur an hour earlier just because some political entity decreed it so.
'alarm' time: Like appointment time but no zone info as a fundamental. If you set your alarm to wake you up at 8 in the morning and you hop in a plane and fly west a bunch, you want the alarm to still go off at 8 in the morning local time: The # of seconds until the alarm goes off should change as you move across zones.
So, what is your time value intended to represent?
If 'solarflares' time.
Then the job is to first convert this into a java.time.Instant object, and take it from there. For example, convert back to appointment time via .atZone(), and then print it to a string that looks like that using a java.time.format.DateTimeFormatter. Imagine the input was in singapore time instead, then with this strategy the output is still in CET. Also, I get the feeling you showed the string not because you need the string to be formatted like that, but because you erroneously think that java stores time in this string format. It doesn't; java stores appointment time as an object with a field for year, month, day, etc. The printing of this to a string is separated out, and controlled by a formatter. You can make a formatter to print it any way you please.
Parsing this to a j.t.Instant value can be done based on the GMT+0100, you can ignore the CEST trailing text.
If 'appointments' time.
Then you need to parse this out which is non-trivial; the GMT+0100 is not what you wanted, that IS a legal zone, but not a useful one (no country in the CEST zone uses GMT+0100. There are places on the planet that are GMT+0100 year round. They are not, however, anywhere near central europe). Thus, the relevant bits are everthing except GMT+0100, including CEST, and that is not a standard date format, and 'Central European Standard Time' is not a thing java.time can recognize as far as I know. You'll need a table of all the possible strings that typescript can generate at that point.
If 'alarm time'
Then you can just stop parsing after the final :00 and toss the rest. Use a regexp to strip it out, then parse into a LocalDateTime using the LocalDateTime.of(stringValue, formatter) method. Easy enough.
A note of advice
Try to course your TypeScript to print this stuff in something other than that. One great way to do it is to combine solarflares time with an explicit zone (like Europe/Amsterdam, not like Central European Standard Time). This is much more easily reparsed into any of the 3 different conceptual ways to refer to time.
You can use epoch time to share time between client and server, it´s an easy way.
Typescript epoch time management
const epoch = new Date().getTime();
console.log(epoch);
const date = new Date(epoch);
console.log(date);
Result:
1609801111672
Date Mon Jan 04 2021 22:58:31 GMT+0000 (Western European Standard Time)
Java epoch time management with java.util.Date
long epoch = new Date().getTime();
log.debug( "Epoch: {}", epoch );
Date date = new Date(epoch);
log.debug( "Date: {}", date );
Result
Epoch: 1609801111672
Date: 2021-01-04T22:58:31.672Z
I have to compare 2 dates in Java 8 to get the difference of minutes. Now I am using java.utils.Date to store my dates but I am unable to find out how to get the difference in minutes. Also, the dates to be compared might be in 2 different time zones which should be taken into account if present. How do I proceed with this?
Example dates to be compared :
Mon Oct 12 12:20:00 IST 2020
Mon Oct 05 09:56:57 GMT 2020
The time zone difference itself does not pose any problem. Java handles that nicely. You have a problem in IST being ambiguous, though, it may stand for Irish Summer Time, Israel Standard Time, India Standard Time or something else.
java.time
I recommend you use java.time, the modern Java date and time API, for your date and time work.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz uuuu", Locale.ENGLISH);
String aDateTimeString = "Mon Oct 12 12:20:00 IST 2020";
String anotherDateTimeString = "Mon Oct 05 09:56:57 GMT 2020";
ZonedDateTime aDateTime = ZonedDateTime.parse(aDateTimeString, formatter);
ZonedDateTime anotherDateTime = ZonedDateTime.parse(anotherDateTimeString, formatter);
long differenceInMinutes = ChronoUnit.MINUTES.between(anotherDateTime, aDateTime);
System.out.format("The times are %s and %s%n", aDateTime, anotherDateTime);
System.out.format("Difference is %d minutes%n", differenceInMinutes);
Output is:
The times are 2020-10-12T12:20Z[Atlantic/Reykjavik] and 2020-10-05T09:56:57Z[GMT]
Difference is 10223 minutes
Java has interpreted IST as Icelandic time. You might not have intended that. But the calculation of difference across time zones works.
I provide a link below to how to control how Java interprets IST.
Links
Oracle tutorial: Date Time explaining how to use java.time.
An answer of mine demonstrating how to control the interpretation of IST time zone abbreviation
While troubleshooting a glitch, something strange in this method behavior appears.
Context
Some countries use to save some daylight by shifting time. For example, in the timezone "Europe/Paris", each year, time shifts 1 hour forwards end March and 1 hour backwards end October, both between 2 AM and 3 AM. This causes, for example, the date October, the 30th 2016 at 02:15 AM to exist twice.
Fortunately, both dates does not have the same timestamp (ms) amount, neither readable representation :
Before time shift : Sun Oct 30 02:15:00 CEST 2016 (+0200 from UTC)
After time shift : Sun Oct 30 02:15:00 CET 2016 (+0100 from UTC)
Issue
After instantiating a GregorianCalendar object at the Paris timezone (using SimpleDateFormat), we get our 02:15 AM before backward shift as expected.
But if we want to set minutes to this object using .set(), the +0200 offset information gets corrupted to +0100 ("same time", but after time shift)
Is there any means of doing it this way, as the method .add() actually preserves the offset information?
Example
// Instantiation
GregorianCalendar gc1 = new GregorianCalendar(TimeZone.getTimeZone("Europe/Paris"));
gc1.setTime(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss Z").parse("2016-10-30 02:15:00 +0200"));
GregorianCalendar gc2 = (GregorianCalendar) gc1.clone();
System.out.println(gc1.getTime()); // Output : Sun Oct 30 02:15:00 CEST 2016 ; OK
System.out.println(gc2.getTime()); // Output : Sun Oct 30 02:15:00 CEST 2016 ; OK
// Set/add minutes
gc1.set(Calendar.MINUTE, 10);
gc2.add(Calendar.MINUTE, 10);
System.out.println(gc1.getTime()); // Output : Sun Oct 30 02:10:00 CET 2016 ; Unexpected
System.out.println(gc2.getTime()); // Output : Sun Oct 30 02:25:00 CEST 2016 ; OK
An ugly alternative is to subtract 1 hour from gc1 after setting the value:
gc1.set(Calendar.MINUTE, 10);
gc1.add(Calendar.HOUR, -1);
The result will be Sun Oct 30 02:10:00 CEST 2016.
Unfortunately that seems to be the best solution available for Calendar API. This behaviour of set method was reported as a bug, and the recommendation in JDK bug tracker was to use add to "fix" it:
During the "fall-back" period, Calendar doesn't support disambiguation and the given local time is interpreted as standard time.
To avoid the unexpected DST to standard time change, call add() to reset the value.
I'm using Java 8, so it seems that this bug was never fixed.
Java new Date/Time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only differences are:
the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
conversion from/to the old Calendar API
To convert a GregorianCalendar to the new API, you can do:
// Paris timezone
ZoneId zone = ZoneId.of("Europe/Paris");
// convert GregorianCalendar to ZonedDateTime
ZonedDateTime z = Instant.ofEpochMilli(gc1.getTimeInMillis()).atZone(zone);
In Java 8, you can also do:
ZonedDateTime z = gc1.toInstant().atZone(zone);
To get the date in the same format produced by java.util.Date you can use a DateTimeFormatter:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
System.out.println(fmt.format(z));
The output is:
Sun Oct 30 02:15:00 CEST 2016
I used a java.util.Locale to force the locale to English, so the month name and day of week are formatted correclty. If you don't specify a locale, it'll use the system's default, and it's not guaranteed to always be English (and the default can also be changed without notice, even at runtime, so it's better to always make it explicit which one you're using).
With this API you can add or set the minutes easily:
// change the minutes to 10
ZonedDateTime z2 = z.withMinute(10);
System.out.println(fmt.format(z2)); // Sun Oct 30 02:10:00 CEST 2016
// add 10 minutes
ZonedDateTime z3 = z.plusMinutes(10);
System.out.println(fmt.format(z3)); // Sun Oct 30 02:25:00 CEST 2016
The output will be:
Sun Oct 30 02:10:00 CEST 2016
Sun Oct 30 02:25:00 CEST 2016
Note that in the new API, classes are immutable, so with and plus methods return a new instance.
To convert a ZonedDateTime back to GregorianCalendar, you can do:
gc1.setTimeInMillis(z.toInstant().toEpochMilli());
In java 8, you can also do:
gc1 = GregorianCalendar.from(z);
To parse the input 2016-10-30 02:15:00 +0200, you must use another formatter:
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss XX")
.withZone(ZoneId.of("Europe/Paris"));
ZonedDateTime z = ZonedDateTime.parse("2016-10-30 02:15:00 +0200", parser);
I had to set the timezone using withZone method, because just the offset +0200 is not enough to determine it (more than one timezone can use this same offset and the API can't decide which one to use)
This question already has answers here:
How to Format ISO-8601 in Java
(3 answers)
Closed 5 years ago.
I have a problem when converting the following ISO string 2017-09-01T01:00:00.000Z into a date.
I'm using SimpleDateFormat as follows
SimpleDateFormat stringToDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Date date = stringToDate.parse("2017-09-01T01:00:00.000Z");
The date object output has a date that looks like this
Fri Sep 01 01:00:00 MDT 2017
When I should get an output of
Fri Sep 01 01:00:00 UTC 2017
OR
Fri Aug 31 19:00:00 MDT 2017
It looks like it is not doing the timezone conversion correctly because the time is unchanged, but the timezone has been when neither or both should be changed.
The single quotes around the 'Z' mean that it's not interpreted as a time zone specifier for UTC: it's simply a literal Z in the string, which is discarded.
As you are not setting a timezone specifically on the SimpleDateFormat, the date is parsed in your JVM's default timezone.
Date.toString() uses your JVM's default timezone. There is no timezone in a Date. If you want to print in a specific timezone, you need to use a SimpleDateFormat to print it.
You should use the java.time classes for handling dates in modern Java.
Date doesn't store a timezone, and Date.toString() uses the system default timezone when rendering.
You could also try this function call to create Calendar instance, it should support yyyy-MM-dd'T'HH:mm:ss.SSSZ format.
Calendar cal = javax.xml.bind.DatatypeConverter.parseDateTime(ymd);
edit: hmm you said Android ok this class may not be available.