Other system send for us Timestamp in their time zone.If we run that in cloud in other system is +2 hours. Local is good because the server is the same time zone. How can I be sure that the time will always be right?
String TIME_STAMP_FORMAT = "yyyy-MM-dd-HH.mm.ss.SSSSSS";
DateTimeFormatter TIME_STAMP_FORMATTER = DateTimeFormatter.ofPattern(TIME_STAMP_FORMAT, Locale.getDefault());
private static Timestamp parseTimestamp(String dateString) {
try {
return Timestamp.valueOf(LocalDateTime.parse(dateString, TIME_STAMP_FORMATTER));
} catch (DateTimeParseException e) {
log.error("Not able to parse timestamp", e);
}
return null;
}
Date afterParse = parseTimestamp('2018-12-31-12.30.50.000200')
tl;dr
How can I be sure that the time will always be right?
Include an indicator of time zone or offset-from-UTC with your date-time input string.
Use standard ISO 8601 formats when exchanging date-time values.
Use only java.time classes in Java. Never use Date, Timestamp, Calendar, etc.
Tip: Adjust values from other zones to UTC before sending (generally speaking).
If not possible, then here is a workaround. This assumes you know the time zone intended by the sender of this poor data.
LocalDateTime // Represent a date and time-of-day without the context of a time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline. A meaningless value until you assign a zone/offset.
.parse(
"2018-12-31-12.30.50.000200" , // Avoid such custom formats. Use only ISO 8601 when exchanging date-time values textually.
DateTimeFormatter.ofPattern( "uuuu-MM-dd-HH.mm.ss.SSSSSS" ) // Define formatting pattern to match youre input.
) // Returns a `LocalDateTime` object.
.atZone( // Give meaning to the `LocalDateTime` object by applying a time zone.
ZoneId.of( "Africa/Tunis" ) // Always specify a time zone with `Continent/Region` name, never the 2-4 character pseudo-zones popularly seen in the media.
) // Returns a `ZonedDateTime` object.
.toInstant() // Adjust from a time zone to UTC by extracting an `Instant` object. Same moment, same point on the timeline, different wall-clock time.
See this code run live at IdeOne.com.
Best to avoid java.util.Date class. But if you must interoperate with old code not yet updated to java.time, you can convert. Call on the new methods added to the old classes such as Date.from( Instant ).
Avoid legacy classes
Never use java.sql.Timestamp nor java.util.Date. All of the date-time classes bundled with the earliest versions of Java are now legacy, per the adoption of JSR 310. Use only the modern java.time classes.
Wrong data type
You are using the wrong data type. To track a moment, a specific point on the timeline, you must have a time zone or offset-from-UTC. The LocalDateTime class exactly the wrong class to use here. That class purposely lacks any concept of zone or offset. So it is the opposite of what you want.
To track a moment, use Instant, OffsetDateTime, or ZonedDateTime.
Where the java.time classes have methods with an optional time zone (ZoneId) or offset-from-UTC (ZoneOffset) argument, consider the argument required. Always pass a zone/offset. Then you never need worry about how the sysadmin is setting the JVM’s current default time zone at runtime.
ZonedDateTime.now( // Capture the current moment as seen through the wall-clock time used by the people of a particular region (a time zone).
ZoneId.of( "Pacific/Auckland" )
)
Or, use Instant which is always in UTC, by definition.
Instant.now() // Capture the current moment in UTC.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ISO 8601
Your question is not clear, but it seems you are receiving an input string for a date-time in a custom format. I suggest you educate the people publishing that data about the ISO 8601 standard. This standard defines practical formats for date-time values being exchanged between systems textually.
The java.time classes use the ISO 8601 formats by default when parsing/generating strings.
Workaround
If the data publisher is sending you values such as 2018-12-31-12.30.50.000200 in order to communicate a moment, they have failed. A date and time-of-day without a zone or offset is useless, like communicating an amount of money without indicating a currency.
Do you know for certain the time zone that was implicitly assumed by the sender of this faulty data input? If so, apply it, as a clumsy stop-gap measure for their poor practice.
First parse your input as a LocalDateTime given that it lacks any indicator of zone/offset.
String input = "2018-12-31-12.30.50.000200" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd-HH.mm.ss.SSSSSS" ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
Apply a ZoneId to get a ZonedDateTime object, thereby adjusting to view the moment through the wall-clock time used by the people of that particular region.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ldt.atZone( ldt ) ;
Generally best to work with moments in UTC, unless you have a specific reason to use a time zone (such as presentation to user). So extract an Instant from your ZonedDateTime.
Instant instant = zdt.toInstant() ;
The Z at the end of an ISO 8601 compliant string means UTC, and is pronounced “Zulu”.
See this code run live at IdeOne.com.
input: 2018-12-31-12.30.50.000200
ldt: 2018-12-31T12:30:50.000200
zdt: 2018-12-31T12:30:50.000200+09:00[Asia/Tokyo]
instant: 2018-12-31T03:30:50.000200Z
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Just a small supplement to Basil Bourque’s clever and very informative answer.
I know the date is in CET timezone.
I am sorry, this is not enough. Central European Time (CET) is the common term for quite many European and African(!) time zones the details of which differ. The European ones are generally at offset +01:00 during standard time and at +02:00 during summer (known as Central European Summer Time or CEST). The African ones are at +01:00 all year. For past dates, just a few decades back, some zones used summer time (DST), others didn’t, some were at +00:00, +01:00 or +02:00, and further back in history many other offsets were used, generally not whole hours.
The future is even worse! It has been suggested that the European Union abandons summer time and leaves it to each member state whether they will use permanent standard time or permanent summer time, avoiding the time adjustments in spring and autumn. There is a power struggle going on about this, so we don’t know whether it will happen, nor what each member state chooses. So even if you could tell me the exact time zone of your string from the other system (for example, Europe/Sarajevo), no one knows yet whether 2019-11-01-00.30.50.000200 — less than 7 months from now — will be at offset +01:00 or +02:00.
Link: European MPs vote to end summer time clock changes on BBC News.
Related
I have string of the pattern "yyyy-MM-dd'T'HH:mm:ssZ" which I want to convert to ZonedDateTime format using Java.
Input String Example: "2019-11-23T10:32:15+12:24"
Output: ZonedDateTime
Edit: I have tried this but it does not work.
ZonedDateTime convertToZonedDateTime(final String source) {
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = dateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
I have this solution which works for string "2018-04-05 19:58:55" produces output 2018-04-05T19:58:55+05:30[Asia/Kolkata] but when I change the pattern in function to "yyyy-MM-dd'T'HH:mm:ssZ" and input string to 2019-11-23T10:32:15+12:24 it does not work due to ParseException: Unparsable data.
I need ZonedDateTime format for an API which expects the input time in that format.
tl;dr
OffsetDateTime // Represent a moment as a date with time-of-day in the context of an offset-from-UTC (a number of hours-minutes-seconds).
.parse( // Parse text into a date-time object.
"2019-11-23T10:32:15+12:24" // The offset of +12:24 looks suspicious, likely an error.
) // Returns an `OffsetDateTime` object.
Semantically, we are done at this point with a OffsetDateTime object in hand.
But you claim to be using an API that demands a ZoneDateTime object. We have no known time zone to apply, so let’s apply UTC (an offset of zero hours-minutes-seconds).
OffsetDateTime // Represent a moment as a date with time-of-day in the context of an offset-from-UTC (a number of hours-minutes-seconds).
.parse( // Parse text into a date-time object.
"2019-11-23T10:32:15+12:24" // The offset of +12:24 looks suspicious, likely an error.
) // Returns an `OffsetDateTime` object.
.atZoneSameInstant( // Convert from `OffsetDateTime` to `ZonedDateTime` by applying a time zone.
ZoneOffset.UTC // This constant is a `ZoneOffset` object, whose class extends from `ZoneId`. So we can use it as a time zone, though semantically we are making a mess.
) // Returns a `ZonedDateTime` object.
.toString() // Generate text in standard ISO 8601 format.
See this code run live at IdeOne.com.
2019-11-22T22:08:15Z
Caveat: The offset on your example input string looks wrong to me.
Details
You need to understand some concepts for date-time handling.
Offset
A offset-from-UTC is merely a number of hours-minutes-seconds ahead of, or behind, the meridian line drawn at the Greenwich Royal Observatory.
In Java, we represent an offset with the ZoneOffset class. A date and time-of-day in the context of an offset is represented with the OffsetDateTime class. Such an object represents a moment, a specific point on the timeline.
Time zone
A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region. These changes are determined by politicians. So these changes can be arbitrary and capricious, and happen surprisingly often, often with little or no warning. In North America, for example, most regions have adopted Daylight Saving Time (DST) nonsense, resulting in the offset changing twice a year. Currently there is a fad amongst politicians to quit DST changes while staying permanently year-round on “summer time”, one hour ahead of standard time.
There is a database cataloging these changes. The tZ data is a file maintained by IANA listing changes worldwide. You’ll likely find copies of this data in your host OS, in enterprise-quality database management systems such as Postgres, and in your Java Virtual Machine. Be sure to keep these up-to-date with changes in zones you care about.
Time zones have names in the format of Continent/Region. For example, Africa/Tunis, Europe/Paris, and Asia/Kolkata.
OffsetDateTime
So an input string like "2019-11-23T10:32:15+12:24" has no indicator of time zone, only an offset. So we must parse it an a OffsetDateTime.
OffsetDateTime odt = OffsetDateTime.parse( "2019-11-23T10:32:15+12:24" ) ;
Asking for that as a ZonedDateTime makes no sense. We cannot reliably determine a time zone merely from an offset. Many time zones may share an offset for some pints in time.
Also, that particular input string 2019-11-23T10:32:15+12:24 is suspect. That offset of twelve hours and twenty-four minutes does not map to any current time zone. Are you sure it is correct?
You can convert your OffsetDateTime to a ZonedDateTime by specifying a time zone to use in adjustment. I suggest using UTC. While this works technically, semantically it is confusing. Moments in UTC are best represented by OffsetDateTime rather than ZonedDateTime. But apparently you are interoperating with code that demands a ZonedDateTime specifically, so c’est la vie.
ZonedDateTime zdt = odt.atZoneSameInstant( ZoneOffset.UTC ) ;
Instant
Tip: Generally, APIs should be written to hand off moments as an Instant object, which is always in UTC by definition.
LocalDateTime
You present another string input, "2018-04-05 19:58:55". This input lacks any indicator of time zone or offset-from-UTC. So we cannot know if this means almost-8PM in Tokyo Japan, or almost-8PM in Toulouse France, or almost-8PM in Toledo Ohio US — which are all events happening several hours apart, different points on the time zone.
Such a value must be parsed as a LocalDateTime. Replace the SPACE in the middle with a T to comply with ISO 8601 standard formatting.
LocalDateTime ldt = LocalDateTime.parse( "2018-04-05 19:58:55".replace( " " , "T" ) ) ;
The resulting object does not represent a moment, is not a point in the timeline. Such an object represents potential moments along a spectrum of about 26-27 hours, the range of time zones around the globe.
ZonedDateTime
If you are certain that input string was intended for a particular time zone, apply a ZoneId to get a ZonedDateTime. Then you have determined a moment, a specific point on the timeline.
ZoneId z = ZonedId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
You can parse the input date time string into OffsetDateTime and then convert it into ZonedDateTime
String inputDate = "2019-11-23T10:32:15+12:24";
OffsetDateTime offset = OffsetDateTime.parse(inputDate);
ZonedDateTime dateTime = offset.toZonedDateTime();
If you just need ZonedDateTime at same local time with ZoneId then use atZoneSimilarLocal
ZonedDateTime dateTime = offset.atZoneSimilarLocal(ZoneId.systemDefault());
It’s unclear why you think you want a ZonedDateTime, and if you do, in which time zone. A bit of the following has been said already, but I would like to give you three suggestions to choose from:
You don’t need a ZonedDateTime. An OffsetDateTime fits your string better.
If you want a ZonedDateTime in your default time zone, which makes sense, use OffsetDateTime.atZoneSameInstant() (as in the answer by Basil Bourque).
If you just want a ZonedDateTime representation of your string, the one-arg ZonedDateTime.parse() parses it directly.
Use OffsetDateTime
Your string contains an offset, +12:34, and not a time zone, like Pacific/Galapagos. So OffsetDateTime is more correct to represent its content.
String inputStringExample = "2019-11-23T10:32:15+12:24";
OffsetDateTime dateTime = OffsetDateTime.parse(inputStringExample);
System.out.println(dateTime);
Output from this snippet is:
2019-11-23T10:32:15+12:24
I agree with the comment by Basil Bourque, the offset of +12:24 doesn’t look like a real-world UTC offset, but it’s fine for a Stack Overflow example. In 2019 most offsets are on a whole hour and the rest generally on a whole quarter of an hour, so 24 minutes is not used. Historic offsets include many with both minutes and seconds.
I am exploiting the fact that your string is in ISO 8601 format. The classes of java.time parse the most common ISO 8601 variants as their default, that is, without any explicit formatter. Which is good because writing a format pattern string is always error-prone.
Use OffsetDateTime.atZoneSameInstant()
Your call to ZoneId.systemDefault() in the code in the question seems to suggest that you want a ZonedDateTime in your default time zone. On one hand this use of ZonedDateTime seems reasonable and sound. On the other hand relying on ZoneId.systemDefault() is shaky since the default time zone of your JVM can be changed at any time by another part of your program or any ther program running in the same JVM.
ZonedDateTime dateTime = OffsetDateTime.parse(inputStringExample)
.atZoneSameInstant(ZoneId.systemDefault());
System.out.println(dateTime);
Output in my time zone:
2019-11-22T23:08:15+01:00[Europe/Copenhagen]
Parse directly
If you just need a ZonedDateTIme for an API that requires one (for most purposes a poor design), just parse your string into one:
ZonedDateTime dateTime = ZonedDateTime.parse(inputStringExample);
2019-11-23T10:32:15+12:24
Output is indistinguishable from the one we got from OffsetDateTime, but you have got the required type now.
Stay far away from SimpleDateFormat and Date
In the code in your question you tried to use SimpleDateFormat for parsing your string. Since you can use java.time, the modern Java date and time API, stick to it and forget everything about the old date and time classes. The modern API gives you all the functionality you need. In case we had needed a formatter for parsing, the modern DateTimeFormatter would have been the class to use.
What went wrong in your code?
… it does not work due to ParseException: Unparsable data.
Z in your format pattern string is for RFC 822 time zone offset. This is without colon and would have parsed +1224, but not +12:24.
Link
Wikipedia article: ISO 8601
I have a java.util.Date object, or a java.util.Calendar object. How do I convert that to the right type in java.time framework?
I have heard that we should now be doing the bulk of our business logic with java.time types. When working with old code not yet updated for java.time I need to be able to convert back and forth. What types map to java.util.Date or java.util.Calendar?
Yes, you definitely should be using the java.time framework whenever possible.
Avoid old date-time classes
The old date-time classes including java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat and such have proven to be poorly designed, confusing, and troublesome. Avoid them where you can. But when you must interoperate with these old types, you can convert between old and new.
Read on for a basic introduction, somewhat over-simplified, to orient you in moving back-and-forth between the old and new date-time classes.
java.time
The java.time framework is defined by JSR 310, inspired by the highly-successful Joda-Time library, and extended by the ThreeTen-Extra project. The bulk of the functionality was back-ported to Java 6 & 7 in the ThreeTen-Backport project, with a further adaptation for Android in the ThreeTenABP project.
What java.time type matches java.util.Date? Well, a java.util.Date object basically represents a moment on the timeline in UTC, a combination of a date and a time-of-day. We can translate that to any of several types in java.time. Each is discussed below. Note that some new methods have been added to the old date-time classes to facilitate conversions.
Instant
The building block in java.time is an Instant, a moment on the timeline in UTC with a resolution of nanoseconds.
Generally you should do much of your business logic in UTC. In such work, Instant will be used frequently. Pass around Instant objects, applying a time zone only for presentation to a user. When you do need to apply an offset or time zone, use the types covered further below.
From java.util.Date to Instant
Given that both Instant and java.util.Date are a moment on the timeline in UTC, we can easily move from a java.util.Date to an Instant. The old class has gained a new method, java.util.Date::toInstant.
Instant instant = myUtilDate.toInstant();
You can go the other direction, from an Instant to a java.util.Date. But you may lose information about the fractional second. An Instant tracks nanoseconds, for up to nine digits after the decimal place such as 2016-01-23T12:34:56.123456789Z. Both java.util.Date & .Calendar are limited to milliseconds, for up to three digits after the decimal place such as 2016-01-23T12:34:56.123Z. In this example going from Instant to Date means truncation of the 456789.
java.util.Date myUtilDate = java.util.Date.from(instant);
From java.util.Calendar to Instant
What about a java.util.Calendar instead of a java.util.Date? Internal to the Calendar object, the date-time is tracked as a count of milliseconds from the epoch reference date-time of the first moment of 1970 in UTC (1970-01-01T00:00:00.0Z). So this value can be converted easily to an Instant.
Instant instant = myUtilCalendar.toInstant() ;
From java.util.GregorianCalendar to ZonedDateTime
Even better, if your java.util.Calendar object is actually a java.util.GregorianCalendar you can easily go directly to a ZonedDateTime. This approach has the benefit of retaining the embedded time zone information.
Downcast from the interface of Calendar to the concrete class of GregorianCalendar. Then call the toZonedDateTime and from methods to go back and forth.
if (myUtilCalendar instanceof GregorianCalendar) {
GregorianCalendar gregCal = (GregorianCalendar) myUtilCalendar; // Downcasting from the interface to the concrete class.
ZonedDateTime zdt = gregCal.toZonedDateTime(); // Create `ZonedDateTime` with same time zone info found in the `GregorianCalendar`
}
Going the other direction…
java.util.Calendar myUtilCalendar = java.util.GregorianCalendar.from(zdt); // Produces an instant of `GregorianCalendar` which implements `Calendar` interface.
As discussed above, beware that you may be losing information about the fraction of a second. The nanoseconds in the java.time type (ZonedDateTime) gets truncated to milliseconds in the .Calendar/.GregorianCalendar.
OffsetDateTime
From an Instant we can apply an offset-from-UTC to move into a wall-clock time for some locality. An offset is a number of hours, and possibly minutes and seconds, ahead of UTC (eastward) or behind UTC (westward). The ZoneOffset class represents this idea. The result is an OffsetDateTime object.
ZoneOffset offset = ZoneOffset.of("-04:00");
OffsetDateTime odt = OffsetDateTime.ofInstant(instant, zoneOffset);
You can go the other direction, from an OffsetDateTime to a java.util.Date. Extract an Instant and then proceed as we saw in code above. As discussed above, any nanoseconds get truncated to milliseconds (data loss).
java.util.Date myUtilDate = java.util.Date.from(odt.toInstant());
ZonedDateTime
Better yet, apply a full time zone. A time zone is an offset plus rules for handling anomalies such as Daylight Saving Time (DST).
Applying a ZoneId gets you a ZonedDateTime object. Use a proper time zone name (continent/region). Never use the 3-4 letter abbreviations commonly seen such as EST or IST as they are neither standardized nor unique.
ZoneId zoneId = ZoneId.of("America/Montreal");
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId);
You can go the other direction, from an ZonedDateTime to a java.util.Date. Extract an Instant and then proceed as we saw in code above. As discussed above, any nanoseconds get truncated to milliseconds (data loss).
java.util.Date myUtilDate = java.util.Date.from( zdt.toInstant() );
And we saw further above that a ZonedDateTime may be converted to a GregorianCalendar.
LocalDate
Sometimes you may want a date-only value, without time-of-day and without time zone. For that, use a java.time.LocalDate object.
See this Question for more discussion, Convert java.util.Date to java.time.LocalDate, especially this Answer written by the main man behind the invention of both Joda-Time and java.time.
The key is to go through a ZonedDateTime (as generated in code above). We need a time zone to determine a date. The date varies around the world, with a new day dawning earlier in the east. For example, after midnight in Paris is a new day while still “yesterday” in Montréal. So while a LocalDate does not contain a time zone, a time zone is required to determine a LocalDate.
LocalDate localDate = zdt.toLocalDate();
Converting in the other direction from LocalDate to a date-time means inventing a time-of-day. You can choose any time-of-day that makes sense in your business scenario. For most people, the first moment of the day makes sense. You may be tempted to hard code that first moment as the time 00:00:00.0. In some time zones, that time may not be valid as the first moment because of Daylight Saving Time (DST) or other anomalies. So let java.time determine the correct time with a call to atStartOfDay.
ZonedDateTime zdt = localDate.atStartOfDay(zoneId);
LocalTime
On rare occasion you may want only a time-of-day without a date and without a time zone. This concept is represented by the LocalTime class. As discussed above with LocalDate, we need a time zone to determine a LocalTime even though the LocalTime object does not contain (does not ‘remember’) that time zone. So, again, we go through a ZonedDateTime object obtained from an Instant as seen above.
LocalTime localTime = zdt.toLocalTime();
LocalDateTime
As with the other two Local… types, a LocalDateTime has no time zone nor offset assigned. As such you may rarely use this. It gives you a rough idea of a date-time but is not a point on the timeline. Use this if you mean some general date and some time that might be applied to a time zone.
For example, “Christmas starts this year” would be 2016-12-25T00:00:00.0. Note the lack of any offset or time zone in that textual representation of a LocalDateTime. Christmas starts sooner in Delhi India than it does in Paris France, and later still in Montréal Québec Canada. Applying each of those areas’ time zone would yield a different moment on the timeline.
LocalDateTime ldt = zdt.toLocalDateTime();
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
I have a Java Application running in my Ubuntu Server in USA and configure CEST Time Zone.
If I run Date command in terminal it return date in CEST Zone time - this is perfect.
But In Java if I run the following code
System.out.println (new Date ());
It returns me time in EDT. What configuration am I missing.
You have to be careful in interpreting date objects from the display you get in console because they are formatted using the default TimeZone of the VM on which this program is running (which by default inherits it from timezone of OS).
Of course you can supply your own TimeZone as explained in the answer by Jesper. But while doing so I would strongly recommend to use IANA timezone identifiers like America/New_York instead of EST. More so because abbreviations having "standard" do not take into account day light savings.
So if you simply print the date object on console and you are not getting expected result, chances are high that you have your server timezone is set to wrong value or your OS is set at wrong timezone.
For changing the JVM timezone you can use this parameter on startup
-Duser.timezone="America/New_York"
You say the server is configured to be in the CEST timezone, but according to Java the default timezone is EDT. Java gets the default timezone from the operating system, so probably your server is not properly set to be in CEST.
If you want to print the date in a specific timezone, use a DateFormat and set the timezone on it:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("CET"));
System.out.println(df.format(new Date()));
Note: CEST is not a valid timezone according to my Java (Java 7u45). Did you mean "CET"? (CEST is the summertime variant of CET, but if you use CET, Java will automatically display the time in summertime if appropriate).
tl;dr
UTC:
Instant.now() // Instantiate an object capturing the current moment in UTC.
.toString() // Generate a String representing textually that date-time value using standard ISO 8601 format.
2018-03-16T00:57:34.233762Z
Zoned:
ZonedDateTime.now( ZoneId.of( "Africa/Tunis" ) ) // Instantiate an object representing the current moment with a wall-clock time seed by people in a particular region (time zone).
.toString() // Generate a String representing textually that date-time value using standard ISO 8601 format wisely extended to append the name of the time zone in square brackets.
2018-03-16T01:57:34.233762+01:00[Africa/Tunis]
Details
The Answer by Shailendra is spot-on correct.
In addition, the Date class seen in the Question is part of the troublesome old date-time classes that are now legacy, supplanted entirely by the java.time classes.
The replacement for java.util.Date is java.time.Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant::toString ➞ UTC always
When calling the legacy class’ Date::toString method, the unfortunate behavior chosen by its authors is to dynamically apply your JVM’s current default time zone. This creates no end of confusion. Fortunately, the modern class tells the simple truth without adding any time zone: An Instant is always in UTC.
Instant.now().toString()
2018-03-16T00:57:34.233762Z
That strings format is standard ISO 8601 format. The Z on the end is short for Zulu and means UTC.
CEST Zone time
There is no such thing as a time zone named CEST. Such 3-4 letter names are pseudo-zones. They are not standardized. They are not unique(!). Instead use a proper time zone in format of continent/region.
ZoneId z = ZoneId.of( "Europe/Paris" ) ;
You can adjust from UTC to such a time zone by applying a ZoneId to your Instant to get a ZoneDateTime.
Instant instant = Instant.now() ;
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2018-03-16T01:57:34.233762+01:00[Europe/Paris]
Or use the shortcut, ZonedDateTime.now.
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
You can adjust a ZonedDateTime to another time zone as well. Notice that java.time uses immutable objects. So in adjusting we get a new distinct object based on the original but without disturbing the original.
ZoneId zNewYork = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdtNewYork = zdt.withZoneSameInstant( zNewYork ) ;
zdtNewYork.toString(): 2018-03-15T20:57:34.233762-04:00[America/New_York]
Be very clear that instant, zdt, and zdtNewYork are three separate objects that represent the very same moment, the same point on the timeline. Same moment, different wall-clock time.
I have a Java Application running in my Ubuntu Server in USA and configure CEST Time Zone
FYI, generally speaking, the best practice for a server’s default time zone is UTC.
More importantly, the current default time zone of your server OS and JVM should be irrelevant to your Java app.
Rather than rely implicitly on the JVM’s current default time zone, always specify explicitly the desired/expected time zone. Pass the optional ZoneId argument to the various java.time methods as seen in the code above.
(By the way, ditto for Locale - always specify desired/expected locale rather than rely implicitly on current default.)
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I am making a change to some code which runs on a unix box. It sets the time for a field in a database based on the current date and time for London.
The methods I am using are as follows;
private static Date getCurrentTime() {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd-kk:mm:ss.SSS");
format.setTimeZone(TimeZone.getTimeZone("Europe/London"));
Calendar cal = Calendar.getInstance();
Date currentDate = cal.getTime();
try {
return format.parse(format.format(currentDate));
} catch (ParseException e) {
log.error("Error occured while parsing date-->" + e.getMessage());
}
return new Date();
}
private String getStringFromDate(Date date){
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-kk:mm:ss.SSS");
return sdf.format(date);
}
When the message is processed by the java app on the production unix box (which is set to north america time as thats where it is hosted) then when it is inserted into the database it is an hour behind (not being set to BST).
If I run the same code in Eclipse on my desktop, I get the correct time in the database.
I am unsure what might be causing this issue and was hoping someone might be able to help.
Thanks
edit*** at second glance, even the log files on the unix box are an hour behind so on that basis i assume its unix that is causing the issue opposed to my code.
A Date instance is always in UTC (or, it should be unless you've done something wrong). you should store your dates in the db in UTC and convert them to whatever timezone you desire when presenting them to the user. anything else is just asking for trouble.
your code which formats and then parses the Date instance in the same TimeZone is just meaningless.
tl;dr
A Date (and Instant) are always in UTC by definition. So no need to futz with time zone.
Instant.now() // Capture current moment in UTC.
Or, if you must use the troublesome legacy class Date:
java.util.Date.from( Instant.now() ) // Avoid the legacy classes whenever possible. When required, you can convert back-and-forth via new methods added to the old classes as seen here.
Always specify time zone
Never rely on the current default time zone of either your host OS or your JVM. That default value is out of your control and can change at any moment during runtime.
Instead:
Always use the java.time classes rather than the troublesome old legacy classes seen in your code.
Always specify your desired/expected time zone as an optional argument to the various java.time methods rather than rely implicitly on the JVM’s current default.
java.time
You appear to be trying to get the current moment as a java.util.Date object. That legacy class represents a value in UTC, so the time zone is irrelevant.
Instant
The modern replacement for that class is java.time.Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Capturing the current moment is simple: Instant.now.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
If you must have Date to inter-operate with old code not yet updated to java.time, convert by calling new methods added to the old classes.
java.util.Date javaUtilDate = java.util.Date.from( instant ) ;
Either way, be very aware that both a Date and an Instant represent a point on the timeline in UTC, always UTC.
UTC versus London Time
Also, be aware that UTC is not London time, a common misconception given that UTC/GMT is tracked from a point at the Royal Observatory, Greenwich. Actually, London has a history of anomalies in its offset-from-UTC, including the adoption of Daylight Saving Time (DST).
To get London time, assign a ZoneId to get a ZonedDateTime.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Europe/London" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same moment, same point on the timeline, but viewed with a different wall-clock time used by the people of a particular region (time zone).
Generally, best practice is to keep your servers in UTC, and to do as much of your business logic, storage, and exchange of date-time values in UTC. Use a zoned value such as London time only when required either by business logic or presentation to user.
Notice in the code seen above that the current default time zone of any computer or JVM is irrelevant. A change in that default has no effect on your code.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
This may be a very basic question, but i could'nt find any satisfactory answers.Hope my doubts gets clear on stackoverflow.
Q 1. Suppose i have time in a different timezone and i want to convert it to a different timezone, what is the way to do it in Java?
Q 2. Is there any way to get timezone using JavaScript?
Q 3. A timezone is just the representation of time in a particular zone, but actually every zone is at the same time,just representation wise it may be different depending on geographical conditions. - Is this understanding Correct?
possible duplicate link
Suppose i have time in a different timezone and i want to convert it to a different timezone, what is the way to do it in Java?
Create a formatter and set the timezone in there.
Internally, java.util.Date just stores milliseconds since the Epoch in the UTC timezone.
When you use Date.toString() or new SimpleDateFormat() without a timezone, then the default timezone of your VM is used.
So in a sense, Java always converts to your current/default timezone (unless you happen to be in UTC).
Is there any way to get timezone using Java Script?
It depends. You can use getTimezoneOffset() but that gives you only the offset. There is no API to get the client's OSs timezone ID (like UTC, Europe/Berlin, etc.)
A timezone is just the representation of time...
Not really. See above.
Q 1. Suppose i have time in a different timezone and i want to convert it to a different timezone, what is the way to do it in Java?
The modern way is with the java.time classes.
Firstly, do much of your work in UTC. Apply a time zone only where necessary, such as presentation to a user.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = Instant.now();
If you have only an offset-from-UTC rather than a time zone, apply a ZoneOffset to get a OffsetDateTime.
ZoneOffset offset = ZoneOffset.ofHours( -4 );
OffsetDateTime odt = instant.atOffset( offset );
A time zone is an offset-from-UTC (a specific number of hours, minutes, and seconds) plus a set of rules for handling anomalies such as Daylight Saving Time (DST). Represent a time zone with a ZoneId object. Specify a proper time zone name. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
Apply a ZoneId to get a ZonedDateTime.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
You can apply other time zones to either the Instant or the ZonedDateTime.
ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis );
Q 2. Is there any way to get timezone using JavaScript?
The issue of determining a time zone from a web browser has been handled countless times on Stack Overflow already.
So I'll skip this, except to say the upshot: No, not really in a reliable way; When important to know the time zone precisely you must ask the user herself.
Q 3. A timezone is just the representation of time in a particular zone, but actually every zone is at the same time,just representation wise it may be different depending on geographical conditions. - Is this understanding Correct?
No, a time zone is not a date-time moment.
A time zone adds meaningful context to a date-time in the same way that a currency designation adds meaningful context to an amount of money. A date-time without a time zone is just a rough idea of possible moments, not a precise point on the timeline. Noon at Auckland is earlier than noon in Kolkata which is earlier than noon in Paris which is earlier than noon in Montréal Québec.
You can think of it as pseudo-math statement:
Time Zone = ( Offset-from-UTC + set-of-rules-for-anomalies )
An example of an imaginary time zone:
An offset might be “one hour ahead of UTC”, plus
This set of rules: “On this date we will engage DST, on this date we will disengage DST, on this date during World War II we did shift ahead one hour, on this date after World War II we shifted back one hour, on this date our government shifted clocks forward a half-hour to make us distinct from our arch-rival neighbor country, …”.
You can apply a time zone to a point on the timeline. Like looking at art through a lens, it changes your perception but not the artifact itself. Looking at a point on the timeline through the lens of a time zone distorts the time-of-day and possibly the date into that of a particular community’s wall-clock time.
Another pseudo-math equation as a way of thinking about the class representations of a time zone and a moment on the timeline:
ZonedDateTime = Instant + ZoneId
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I can answer to your second question and correct the Aaron Digulla very complete response
Is there any way to get timezone using Java Script?
try to use this library, it will return a TimeZone ID with particular limitation (menthioned in the developer's page):
https://bitbucket.org/pellepim/jstimezonedetect