I am attempting to show transactions over a certain time period using Jodatime.
Our server requires a start date and end date to be in UTC (which is probably obvious). Therefore any business logic around these is using DateTime object with the timezone set to DateTimeZone.UTC, e.g.
mStartDate = DateTime.now(UTC).withTimeAtStartOfDay();
That works well except when it comes to display the time I don't know how to augment it for the local (system default) timezone. Ideally I would like to use the DateUtils formatDateRange function passing in two local timestamps. But the getMillis() function doesn't seem to account for local offsets:
I have also tried this:
mTimePeriodTitle.setText(DateUtils.formatDateRange(mContext, f, mStartDate.getMillis(),
mEndDate.getMillis(), DateUtils.FORMAT_SHOW_TIME,
TimeZone.getDefault().getID()).toString());
But it hasn't made any difference. So my question is how can I get a nicely formatted local date range with 2 UTC timestamps?
If your DateTime is in UTC and you want to convert it to another timezone, you can use the withZone method to do the conversion.
For the examples below, my default timezone is America/Sao_Paulo (you can check yours using DateTimeZone.getDefault()):
// create today's date in UTC
DateTime mStartDate = DateTime.now(DateTimeZone.UTC).withTimeAtStartOfDay();
// date/time in UTC
System.out.println(mStartDate); // 2017-06-13T00:00:00.000Z
// date/time in my default timezone (America/Sao_Paulo)
System.out.println(mStartDate.withZone(DateTimeZone.getDefault())); // 2017-06-12T21:00:00.000-03:00
The output is:
2017-06-13T00:00:00.000Z
2017-06-12T21:00:00.000-03:00
Note that the withZone method correctly converts the date and time to my timezone (in America/Sao_Paulo the current offset is UTC-03:00), so it was adjusted accordingly.
If you want to get just the time (hour/minute/second), you can use toLocalTime() method:
System.out.println(mStartDate.withZone(DateTimeZone.getDefault()).toLocalTime()); // 21:00:00.000
The output is:
21:00:00.000
If you want another format (for example, don't print the 3 digits of fraction-of-second), you can use a DateTimeFormatter. The good thing is that you can set a timezone in the formatter, so you don't need to convert the DateTime:
// create formatter for hour/minute/second, set it with my default timezone
DateTimeFormatter fmt = DateTimeFormat.forPattern("HH:mm:ss").withZone(DateTimeZone.getDefault());
System.out.println(fmt.print(mStartDate)); // 21:00:00
The output is:
21:00:00
To get your range, you can use one of the methods above with your DateTime's (mStartDate and mEndDate), and use the DateTimeFormatter to change to whatever format you need.
PS: what I think you're missing when using getMillis() is that both datetimes (in UTC and in default timezone) represents the same instant. You are just converting this instant to a local time, but the millis is the same (think that, right now, at this moment, everybody in the world are in the same instant (the same millis), but their local times might be different depending on where they are). So, when converting a UTC DateTime to another timezone, we're just finding what is the local time in that zone, that corresponds to the same millis.
You can check this using the getMillis() method on both objects:
System.out.println(mStartDate.getMillis()); // 1497312000000
System.out.println(mStartDate.withZone(DateTimeZone.getDefault()).getMillis()); // 1497312000000
Note that, even if I convert the object to another timezone, the millis remains the same (1497312000000). That's because both represent the same instant, I'm just moving them to another timezone where the respective local time is different.
Java new Date/Time API
Joda-Time it's being discontinued and replaced by the new APIs, so I don't recommend start a new project with it. If that's your case, you can consider using the new Date/Time API, but if you have a big codebase using Joda or don't want to migrate it now, you can desconsider the rest of the answer.
Anyway, even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".*
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. I'm not sure if it's already available to all Android versions (but see the alternative below).
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 a way to use it, with the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is 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.
To get the current date at start of the day in UTC, you can do:
// UTC's today at start of the day
ZonedDateTime utc = LocalDate.now(ZoneOffset.UTC).atStartOfDay(ZoneOffset.UTC);
System.out.println(utc); // 2017-06-13T00:00Z
First I did LocalDate.now(ZoneOffset.UTC) to find the current local date in UTC. If I use just LocalDate.now(), it'll get the current date in my default timezone, which is not what we want (it might be different from UTC, depending on where - and when - you are and what the default timezone is).
Then I used atStartOfDay(ZoneOffset.UTC) to get the start of the day at UTC. I know it sounds redundant to use UTC twice, but the API allows us to use any timezone in this method, and IMO it makes explicit what timezone we want (if the date is in a timezone with Daylight Saving changes, the start of day might not be midnight - the timezone parameter is to guarantee that the correct value is set).
The output is:
2017-06-13T00:00Z
To convert to my default timezone, I can use ZoneId.systemDefault(), which in my case returns America/Sao_Paulo. To convert it and get only the local time part, just do:
System.out.println(utc.withZoneSameInstant(ZoneId.systemDefault()).toLocalTime()); // 21:00
The output is:
21:00
If you want to change it, you can also use a formatter:
// formatter for localtime (hour/minute/second)
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm:ss");
System.out.println(fmt.format(utc.withZoneSameInstant(ZoneId.systemDefault()))); // 21:00:00
The output is:
21:00:00
java.time
The Joda-Time project is now in maintenance mode, with the project advising migration to the java.time classes.
Zones
Our server requires a start date and end date to be in UTC (which is probably obvious).
Yes, use UTC for much of your business logic, as well as for logging, storing, and exchanging date-time values. Think of UTC as the One True Time, with other zones being mere variations. Apply a time zone only when required for specific rules in your business logic or for presentation to the user.
For a value in UTC, use 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 instant = Instant.now() ; // Capture the current moment in UTC.
To see the same moment in a particular time zone, assign a ZoneId to get a ZonedDateTime object. Same moment, same point on the timeline, different wall-clock time.
ZoneId zTunis = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdtTunis = instant.atZone( zTunis ) ;
See the same moment in yet another zone.
ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdtAuckland = instant.atZone( zAuckland );
Strings
So my question is how can I get a nicely formatted local date range with 2 UTC timestamps?
After making the adjustments from UTC to a time zone as shown above, generate strings to represent their value.
To generate a String representing any of those objects in standard ISO 8601 format, simply call toString.
String output = instant.toString() ;
2018-01-23T01:23:45.123456Z
String output = zdtAuckland.toString() :
2018-01-23T14:23:45.123456+13:00[Pacific/Auckland]
To generate a String in other formats, define a formatting pattern. Or let java.time automatically localize.
To localize, specify:
FormatStyle to determine how long or abbreviated should the string be.
Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.
Example:
Locale l = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( l );
String output = zdt.format( f );
mardi 23 janvier 2018 à 14:23:45 heure avancée de la Nouvelle-Zélande
Note that time zone has nothing to do with Locale. One is for content, the other is for presentation.
Interval
When representing a pair of moments, a couple of start-stop moments, use the Interval class found in the ThreeTen-Extra library (linked below). This class represents a pair of Instant objects.
Its toString method generates a string is standard ISO 8601 format. For other formats, and for adjustments into other zones, use the code seen above to apply to each Instant a ZoneId to generate a ZonedDateTime. Access each Instant via getStart & getEnd.
Interval interval = Interval.of( start , stop ) ;
interval.toString(): 2007-12-03T10:15:30/2007-12-04T10:15:30
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, Java SE 10, 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.
Related
This question already has answers here:
How to find the duration of difference between two dates in java?
(18 answers)
Closed 4 years ago.
i wanted to take an input of date and time in the below format and need to calculate the time difference between two, can anyone suggest how to take below string as input and calculate the time difference.
user defined datetime input in java
String startTime= "11/27/2018+09:00:00";
String endTime= "11/28/2018+13:00:00";
The + is a separator (not a sign as in plus or minus).
Senseless input
String startTime= "11/27/2018+09:00";
String endTime= "11/28/2018+13:00";
These inputs do not make sense. Applying an offset-from-UTC such as +09:00 to a date such as 11/27/2018 has no meaning.
For an offset to have meaning, you need a date and a time-of-day.
We can make a guess and assume the people sending the data meant the first moment of the day. If so, they should have said so by including that in the data.
The trick here is that some dates in some time zones do not always start at 00:00:00 time-of-day. Anomalies such as Daylight Saving Time (DST) mean the day may start at a time such as 01:00:00. Unfortunately, your input has only an offset (a number of hours-minutes-seconds) rather than a time zone (Continent/Region name). A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region. Without a time zone, we cannot look up the rules to know the anomalies.
The best you could do is assume the day starts at 00:00:00 and ignore the reality of any anomalies. But this is guesswork and inadvisable. The real solution is to educate the publisher of your data about two things when exchanging date-time values: (a) Use UTC rather than an offset or zone, and (b) write strings in standard ISO 8601 format.
Guesswork
If correcting the source of this data is not feasible, then we can plod on with guesswork.
Extract the date, separate from offset.
String input = "11/27/2018+09:00";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu" );
LocalDate localDate = LocalDate.parse( input.substring( 0 , 10 ) , f );
ZoneOffset zoneOffset = ZoneOffset.of( input.substring( 11 ) );
localDate.toString(): 2018-11-27
zoneOffset.toString(): +09:00
OffsetDateTime odt = OffsetDateTime.of( localDate , LocalTime.MIN , zoneOffset );
2018-11-27T00:00+09:00
We can calculate elapsed time as a Duration. But beware, without the context of time zones, we cannot account for any anomalies that may be occurring in this time period, as discussed above. With only offsets rather than zones, calculations are made using generic 24-hour days. So, again, this is just sloppy guesswork, not a reliable solution.
Duration d = Duration.between( odt , odtLater ) ;
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, 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.
In java 8 there is:
LocalDateTime: use this if you need to deal with date and time.
LocalDate: use this if you need to deal with date only.
ZonedDateTime: use this if you need to deal with date time with time zone.
OffsetDateTime: use this if you need to deal with date time with offset. (the most suitable for your case)
Your case is only use Date and Offset, it's a bit tricky since time zone and offset can only be applied to LocalDateTime (not only date).
However, I think you can solved it like this:
Create a method that convert your date string into OffsetDateTime like this:
private static OffsetDateTime createZonedDateTime (String dateWithTimeOffset)
{
//TODO: assert that dateWithTimeOffset is valid
String date = dateWithTimeOffset.substring (0, 10);
String timeOffset = dateWithTimeOffset.substring (10, 13);
//define your date pattern
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ("MM/dd/yyyy");
return LocalDate.parse (date, formatter) // create LocalDate
.atStartOfDay () // convert it to LocalDateTime with time 00:00:00
.atOffset (ZoneOffset.of(timeOffset)); // apply the offset
}
Then you can simple create your OffsetDateTime like this:
OffsetDateTime startTime = stringToZonedDateTime ("11/27/2018+09:00");
OffsetDateTime endTime = stringToZonedDateTime ("11/28/2018+13:00");
You can create duration using OffsetDateTime like this:
Duration duration = Duration.between (startTime, endTime);
Duration have everything you need related with time duration, for example:
duration.toHours () // will give you the hour duration
I need to parse a UTC date and time string, e.g. 20180531_132001Z into a Java 8 date and time object. How do I go about doing this using Java 8's new date and time libraries? Most examples I see is for LocalDateTime, like this:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss'Z'");
LocalDateTime localDateTime = LocalDateTime.parse("20180531_132001Z", formatter);
System.out.println(localDateTime);
System.out.println(localDateTime.atOffset(ZoneOffset.UTC));
The code outputs:
2018-05-31T13:20:01
2018-05-31T13:20:01Z
Is this considered local time or UTC time? The string value I am parsing is based on UTC, so I am wondering if I need to do anything further before persisting to the database.
If the former, how do I convert that to UTC date and time?
I ultimately need to persist this to a SQL Server database table (column type is [datetime2](7), using [Spring] JDBC.
Update: Based on the comments and answers, I think my question is not well thought out. Putting it another way, if I get an input string and I parse it without factoring any zone or offset, I will get a LocalDateTime object. How do I take that object and convert the encapsulated value to UTC date and time?
LocalDateTime can be misleading. It doesn't represent your local date/time, it represents a local date/time.
It carries no time zone info at all.
That is, it just says for example "it's 13:20". It doesn't say where it's 13:20. It's up to you to interpret the where part.
Due to this LocalDateTime is usually not very useful for carrying timestamps, it's only useful for situations when the timezone is dependent on some context.1
When working with timestamps it's better to use ZonedDateTime or OffsetDateTime instead. These carry the date, time and offset.
So localDateTime.atOffset(ZoneOffset.UTC) will actually return an instance of OffsetDateTime, by interpreting localDateTime as UTC time.
One could argue that you can avoid the interpreting part by parsing with the timezone info in the first place (even though it's always Z):
String example = "20180531_132001Z";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmssX");
OffsetDateTime dateTime = OffsetDateTime.parse(example, formatter);
System.out.println(dateTime); // look ma, no hardcoded UTC
Will print:
2018-05-31T13:20:01Z
The added value is that your code automatically supports timezones (e.g. "20180531_132001+05").
JDBC 4.2 compliant driver may be able to directly address java.time types by calling setObject.
For older JDBC drivers you can convert dateTime to a java.sql.Timestamp or java.util.Date:
java.sql.Timestamp.from(dateTime.toInstant());
java.util.Date.from(dateTime.toInstant());
1 There is almost always some context in which LocalDateTime operates. For example "Flight KL1302 arrives at airport X tomorrow at 13:20". Here the context of "tomorrow at 13:20" is the local time at airport X; it can be determined by looking up the time zone of X.
tl;dr
myPreparedStatement.setObject( // Pass java.time objects directly to database, as of JDBC 4.2.
… , // Indicate which placeholder in your SQL statement text.
OffsetDateTime.parse( // Parse input string as a `OffsetDateTime` as it indicates an offset-from-UTC but not a time zone.
"20180531_132001Z" , // Define a formatting pattern to match your particular input.
DateTimeFormatter.ofPattern( "uuuuMMdd_HHmmssX" ) // TIP: When exchanging date-time values as text, use use standard ISO 8601 formats rather than inventing your own.
) // Returns a `OffsetDateTime` object.
.toInstant() // Returns a `Instant` object, always in UTC by definition.
)
Details
There is some helpful information in the other Answers, but all of them have some misinformation which I tried to correct by posting comments.
Most importantly, your code is using the wrong Java class and the wrong database data type for that given input.
Below is explanation along with a complete code example, using the modern java.time classes with JDBC 4.2 or later.
Z = UTC
DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss'Z'")
Never put single-quotes around vital parts of your input such as you did here with Z. That Z means UTC and is pronounced “Zulu”. It tells us the text of the date and time-of-day should be interpreted as using the wall-clock time of UTC rather than, say, America/Montreal or Pacific/Auckland time zones.
Do not use the LocalDateTime for such inputs. That class lacks any concept of time zone or offset-from-UTC. As such, this class does not represent a moment, and is not a point on the timeline. A LocalDateTime represents the set of potential moments along a range of about 26-27 hours (across all time zones). Use LocalDateTime when you mean any or all time zones rather than one particular zone/offset. In contrast, the Z tells us this input uses the wall-clock time of UTC specifically.
Parsing
Define a formatting pattern to match all important parts of your input string.
String input = "20180531_132001Z" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMdd_HHmmssX" ) ;
By the way, whenever possible, use standard ISO 8601 formats rather than a custom format as seen in your Question. Those formats are wisely designed to be easy to parse by machine and easy to read by humans across cultures while eliminating ambiguity.
Parse as a OffsetDateTime because your input indicates an offset-from-UTC (of zero hours). An offset-from-UTC is merely a number of hours and minutes, nothing more, nothing less.
Use the ZonedDateTime class only if the input string indicates a time zone. A time zone has a Contintent/Region name such as Africa/Tunis. A zone represents the history of past, present, and future changes in the offset used by the people of a particular region.
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;
odt.toString(): 2018-05-31T13:20:01Z
Database
To communicate this moment to a database using JDBC 4.2 and later, we can directly pass the java.time object.
myPreparedStatement.setObject( … , odt ) ;
If your JDBC driver does not accept the OffsetDateTime, extract the simpler class Instant. An Instant is in UTC always, by definition.
Instant instant = odt.toInstant() ;
myPreparedStatement.setObject( … , instant ) ;
And retrieval.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Beware - Wrong datatype in your database
I am not a MS SQL Server user, but according to this documentation, the column data type DATETIME2 is not appropriate to your input. That data type seems to be equivalent to the SQL-standard type DATETIME WITHOUT TIME ZONE. Such a type should never be used when recording a specific moment in history.
Lacking any concept of time zone or offset-from-UTC, that column type should only be used for three situations:
The zone or offset is unknown.This is bad. This is faulty data. Analogous to having a price/cost without knowing the currency. You should be rejecting such data, not storing it.
The intention is “everywhere”, as in, every time zone.Example, a corporate policy that states “All our factories will break for lunch at 12:30" means the factory in Delhi will break hours before the factory in Düsseldorf which breaks hours before the factory in Detroit.
A specific moment in the future is intended, but we are afraid of politicians redefining the time zone.Governments change the rules of their time zones with surprising frequency and with surprisingly little warning (even [no warning at all][10]). So if you want to book an appointment at 3 PM on a certain date, and you really mean 3 PM regardless of any crazy decision a government might make in the interim, then store a LocalDateTime. To print a report or display a calendar, dynamically apply a time zone (ZoneId) to generate a specific moment (ZonedDateTime or Instant). This must be done on-the-fly rather than storing the value.
Since your input is a specific moment, a certain point on the timeline, you should be storing it in the database using a column type akin to the SQL-standard type TIMESTAMP WITH TIME ZONE.
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, Java SE 10, 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.
Maybe this can help you.
public static void main(String... strings) {
OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println(utc.toString());
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy mm dd hh:mm a");
System.out.println(utc.format(format));
}
While you certainly can use LocalDateTime and format it to look like a zoned date time using offset, it would be easier to use an Object designed to store time zone.
ZonedDateTime zonedDateTime = ZonedDateTime.parse("20180531_132001Z", DateTimeFormatter.ofPattern("yyyMMdd_HHmmssX"));
This gives you the option to use Instant to convert to SQL timestamp or any other format without having to hard-code the time zone, especially if time zone is added in the future or changes.
java.sql.Timestamp timestamp = new java.sql.Timestamp(zonedDateTime.toInstant().toEpochMilli());
You can view the timestamp's instant and compare it to the toString, which should be pegged to your timezone, and instant.toString, which pegs to UTC.
System.out.print(timestamp + " " + timestamp.toInstant().toString());
this should do the trick to parse string to LocalDateTime :
String example = "20180531_132001Z";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmssX");
ZonedDateTime dateTime = ZonedDateTime.parse(example, formatter);
See that code run live in IdeOne.com.
dateTime.toString(): 2018-05-31T13:20:01Z
Timestamp timestamp = Timestamp.from(dateTime.toInstant());
Timestamp then is saved into db
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