Simple Java String to java.util.Date conversion adds unwanted daylight saving - java

This is my program snippet
import java.lang.Math;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class Main
{
public static void main(String[] args)
{
String dateTime = "2017-03-12 02:46:00";
// convert string to java.util.Date
try {
SimpleDateFormat e = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = e.parse(dateTime);
System.out.println(d);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
This is the output of that program
Sun Mar 12 03:46:00 PDT 2017
Expected Output
Sun Mar 12 02:46:00 PDT/PST 2017
Apparently, it is adding daylight saving time which occurs on PST at 2017-03-12 02:00:00
Few things I am bounded.
I cannot change server default timezone or anything specific to JVM
I must return back java.util.Date as final value.
Edit:
To some comment pointing me out how java.util.Date only stores long timestamp. Can you please give me a way where this function works
java.util.Date convertStringToDate(String str) {
// code to convert String to Date
}
convertStringToDate("2017-03-12 02:46:00");
should give me 2017-03-12 02:46:00 value in Date class? I don't care about what timezone it provides. It should have that value, whatever timezone it is while printing. Again my JVM is in PST.

Use java.time, not legacy date-time classes
You are using troublesome old date-time classes such as java.util.Date that are now legacy, supplanted by the java.time classes.
LocalDateTime
2016-03-12 02:46:00 value …I don't care about what timezone it provides. It should have that value, whatever timezone it is…
If you truly want to represent that date and time-of-day without regard for time zone, use the LocalDateTime class. This class purposely ignores time zone.
To parse, adjust your input string to comply with the ISO 8601 standard formats used by the java.time classes for parsing/generating strings.
String input = "2016-03-12 02:46:00".replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( input );
But beware: By ignoring time zone you lose the meaning of this date+time. Without the context of a time zone, we do not know if you mean the 2 AM in Auckland NZ, or 2 AM in Kolkata India (some hours later), or 2 AM in Paris France (more hours later), or 2 AM in Montréal Québec (still more hours later). A LocalDateTime is a rough idea about possible moments, but is not actually a point on the timeline.
ZonedDateTime
This is the output of that program Sun Mar 12 03:46:00 PDT 2017
Expected Output Sun Mar 12 02:46:00 PDT/PST 2017
Now you contradict yourself.
By including the PDT or PST with your expected output, you mean a specific moment on the timeline perceived through the lens of a particular region’s wall-clock time. This contradicts your statement that you want "2016-03-12 02:46:00" regardless of time zone. It is crucial that you understand this distinction to properly handle date-time work.
If indeed the intent of the string 2016-03-12 02:46:00 is to represent a moment in the wall-clock time of the left coast of north America (as I guess you meant by PDT), then we must parse that string firstly as a LocalDateTime as it lacks any indicator of time zone, but then immediately adjust it into a time zone to get a ZonedDateTime object.
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 or PDT or PST as they are not true time zones, not standardized, and not even unique(!).
Here I arbitrarily chose America/Los_Angeles as the time zone, as your Question does not mention a specific time zone, only “PDT”.
String input = "2017-03-12 02:46:00".replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( input );
ZoneId z = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = ldt.atZone( z );
But it just so happens that March 12 of 2017 has an anomaly. That is the day when the craziness known as Daylight Saving Time (DST) kicks in. The clocks in much of the left coast of north America at 2 AM jump to 3 AM. There is no two o’clock hour. The day is 23 hours long rather than the usual 24 hours. So your request for 2:46 is asking for a nonexistent moment, an invalid value. The design choice in java.time to resolve this conundrum is to jump forward, following the "Spring Forward" of DST. The result is in the 3 AM hour, 03:46.
See this code run live in IdeOne.com.
input: 2017-03-12T02:46:00
ldt.toString(): 2017-03-12T02:46
zdt.toString(): 2017-03-12T03:46-07:00[America/Los_Angeles]
Note the 2 AM hour becomes the 3 AM hour in that output.
A reasonable person could make arguments for a different design choice in handling this anomaly, such as throwing an Exception. But this is how java.time works. Study the class doc and be sure you understand the behavior on this important topic.
If you want to detect such an anomaly, call toLocalDateTime on the ZonedDateTime object, and compare to the first LocalDateTime. With no anomaly, the pair of LocalDateTime objects will be equal; with an anomaly they will not be equal.
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.
Where to obtain the java.time classes?
Java SE 8 and 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 SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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

SimpleDateFormat - Strange result when parsing Date

I'm currently at a loss about the following simple usage of the SimpleDateFormatter:
import java.text.ParseException;
import java.text.SimpleDateFormat;
public static void main(String[] args) throws ParseException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").parse("2018-12-04T22:22:01+1000"));
}
I'm running this example with JDK 1.8.0_192.
My PC is located at CET (+1000), so timezone is equal. So the expected result would be:
Tue Dec 04 22:22:01 CET 2018
But I get the following output:
Tue Dec 04 13:22:01 CET 2018
Does anyone have an Idea what is happening here?
You give it 2018-12-04T22:22:01+1000, which is 2018-12-04T12:22:01 in UTC. While CET is 1 hour ahead UTC, so you get hour 13.
tl;dr
Your original problem was a typo +1000 vs +0100. Nevertheless, all the advice below still applies. You are using terrible old classes that should be avoided.
OffsetDateTime.parse(
"2018-12-04T22:22:01+1000" , // Input in standard ISO 8601, with the COLON omitted from the offset as allowed by the standard but breaking some libraries such as `OffsetDateTime.parse`.
DateTimeFormatter.ofPattern(
"uuuu-MM-dd'T'HH:mm:ssX"
)
) // Returns a `OffsetDateTime` object.
.toInstant() // Adjust into UTC. Returns an `Instant` object. Same moment, different wall-clock time.
.atZone( // Adjust from UTC to some time zone. Same moment, different wall-clock time.
ZoneId.of( "Europe/Brussels" )
) // Returns a `ZonedDateTime` object.
.toString() // Generate text representing this `ZonedDateTime` object in standard ISO 8601 format but wisely extending the standard by appending the name of the time zone in square brackets.
18-12-04T13:22:01+01:00[Europe/Brussels]
Avoid legacy date-time classes
You are using terrible old date-time classes bundled with the earliest versions of Java. Supplanted years ago by the java.time classes.
Use proper time zones
FYI, CET is not a real time zone.
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(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
You likely mean a time zone such as Europe/Brussels, Europe/Paris, Europe/Berlin, Africa/Tunis, or Europe/Oslo.
ISO 8601
Your input string 2018-12-04T22:22:01+1000 is in standard format, defined by ISO 8601.
The last part +1000 is an offset-from-UTC, meaning a moment ten hours ahead of UTC. So this value was intended for the wall-clock time used by people is some region in the Pacific, such as time zone Australia/Lindeman.
Do not abbreviate the offset notation
That string +1000 is an abbreviation of an offset, omitting the COLON character delimiter between hours and minutes (and seconds, if any). While the standard allows this omission, I suggest always including the COLON: 2018-12-04T22:22:01+10:00. In my experience, some libraries and protocols break when encountering such strings. And the COLON’s inclusion makes the string more readable for humans.
OffsetDateTime
Indeed, the java.time.OffsetDateTime class meant to parse such standard strings by default has a bug in this regard, failing to parse when the COLON is omitted. Discussed at:
Java 8 Date and Time: parse ISO 8601 string without colon in offset
Cannot parse String in ISO 8601 format, lacking colon in offset, to Java 8 Date
Workaround:
OffsetDateTime odt =
OffsetDateTime.parse(
"2018-12-04T22:22:01+1000" ,
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" )
)
;
See code example running live at IdeOne.com.
odt.toString(): 2018-12-04T22:22:01+10:00
Adjust that value into UTC by extracting an Instant object. Instant is always in UTC by definition.
Instant instant = odt.toString() ;
instant.toString(): 2018-12-04T12:22:01Z
Finally, we can adjust into your own parochial time zone.
By CET I assume you meant a time zone such as Europe/Paris.
ZoneId z = ZoneId.of( "Europe/Paris" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
When calling ZonedDateTime::toString, text is generated in standard ISO 8601 format, but wisely extending the standard to append the name of the time zone in square brackets.
zdt.toString(): 2018-12-04T13:22:01+01:00[Europe/Paris]
All three of these objects (odt, instant, & zdt) refer to the same simultaneous moment, the very same point on the timeline. Their only difference is the wall-clock time. If three people on a conference call in Australia, France, and Iceland (always in UTC) all looked up simultaneously to read the current moment from their respective clock hanging on their local wall, they would read three different values for the same simultaneous moment.
See all this code run live at that IdeOne.com page.
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.

Java: Calculate month end date based on timezone

I have method to find month end date based on the timezone.
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("CET"));
calendar.set(
Calendar.DAY_OF_MONTH,
calendar.getActualMaximum(Calendar.DAY_OF_MONTH)
);
System.out.println(calendar.getTime());`
It displays output: Thu Aug 30 18:04:54 PDT 2018.
It should, however, give me an output in CET.
What am I missing?
The Calendar.getTime() method returns a Date object, which you then printed in your code. The problem is that the Date class does not contain any notion of a timezone even though you had specified a timezone with the Calendar.getInstance() call. Yes, that is indeed confusing.
Thus, in order to print a Date object in a specific timezone, you have to use the SimpleDateFormat class, where you must call SimpleDateFormat.setTimeZone() to specify the timezone before you print.
Here's an example:
import java.util.Calendar;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
public class TimeZoneTest {
public static void main(String argv[]){
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("CET"));
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
System.out.println("calendar.getTime(): " + calendar.getTime());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss z");
sdf.setTimeZone(TimeZone.getTimeZone("CET"));
System.out.println("sdf.format(): " + sdf.format(calendar.getTime()));
}
}
Here is the output on my computer:
calendar.getTime(): Fri Aug 31 01:40:17 UTC 2018
sdf.format(): 2018-Aug-31 03:40:17 CEST
This is because Date object doesn't have timezone as part of its state, and getTime() actually returns a date which corresponds to the JVM's timezone, instead you need SimpleDateFormat to format and print the date in your required timezone.
If you try adding the following line of code, you could see that the timezone in the calendar is actually CET.
System.out.println(calendar.getTimeZone().getDisplayName());
tl;dr
YearMonth // Represent a year-month without day-of-month.
.now( // Capture the current year-month as seen in the wall-clock time used by the people of a particular region (a time zone).
ZoneId.of( "Africa/Tunis" ) // Specify your desired time zone. Never use 3-4 letter pseudo-zones such as `CET`.
) // Returns a `YearMonth` object.
.atEndOfMonth() // Determine the last day of this year-month. Returns a `LocalDate` object.
.atStartOfDay( // Let java.time determine the first moment of the day. Not necessarily 00:00:00, could be 01:00:00 or some other time-of-day because of anomalies such as Daylight Saving Time (DST).
ZoneId.of( "Africa/Tunis" )
) // Returns a `ZonedDateTime` object, representing a date, a time-of-day, and a time zone.
java.time
You are using the terrible old Calendar class that was supplanted years ago but the modern java.time classes.
LocalDate
If you need only a date, use LocalDate class. Then the time zone is irrelevant for your output.
But time zone is very relevant for determining the current date. For any given moment, the date varies around the globe by zone.
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 CET or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Europe/Paris" ) ; // Or "Africa/Tunis" etc.
LocalDate today = LocalDate.now( z ) ; // Capture the current date as seen by the wall-clock time used by the people of a certain region (a time zone).
YearMonth
Get the month for that date. Represent a year-month with, well, YearMonth.
YearMonth ym = YearMonth.from( today ) ;
Or skip the LocalDate.
YearMonth ym = YearMonth.now( z ) ;
Get the end of the month.
LocalDate endOfThisMonth = ym.atEndOfMonth() ;
ISO 8601
To generate a String representing that LocalDate object’s value, call toString. The default format is taken from the ISO 8601 standard. For a date-only value that will be YYYY-MM-DD such as 2018-01-23.
String output = endOfThisMonth.toString() ;
If you need another format, use DateTimeFormatter class. Search Stack Overflow for many examples and discussions.
Moment
If you need a moment, you can add a time-of-day and time zone to your LocalDate to get a ZonedDateTime. Or let ZonedDateTime determine the first moment of the day (which is not always 00:00:00!).
ZonedDateTime zdt = LocalDate.atStartOfDay( 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.
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.

DST changes caused an java.text.ParseException: Unparseable date

Following is the code snippet which is throwing an exception:
SimpleDateformat dateFormatter = new SimpleDateFormat("yyyyMMddHHmm");
Date date = dateFormatter.parse("201710010200");
The code above threw exception for all the dates after 2:00 A.M. It ran well till 01:30 A.M.
DayLight saving time was configured (I'm using Australia/Sydney timezone).
After that, I could see logs of 3:00 A.M.
Time between 2:00 A.M. and 3:00 A.M. is not logged too.
Log:
01 Oct 03:02:01 ERROR : Unparseable date: "201710010200"
Caused by: java.text.ParseException: Unparseable date: "201710010200"
at java.text.DateFormat.parse(DateFormat.java:357)
What could be the fix of the problem of the date string "201710010200" not getting parsed, with the right date format specified?
You're trying to parse a date/time that didn't occur.
We now know that this was in the Sydney time zone. At 2am on October 1st 2017 in Sydney, the clocks went forward to 3am. If you were looking at a clock every minute you'd see:
01:58
01:59
03:00
03:01
So any date/time between 2am (inclusive) and 3am (exclusive) simply didn't occur in that time zone. We don't know what produced the values you're trying to parse, but:
If they're timestamps, it would almost certainly be better to both format and parse in UTC. Keep an offset from UTC and potentially a time zone ID if the time zone in which they were produced is important for future analysis.
If they're date/time values which aren't linked to any particular time zone, don't parse them as if they were in a time zone. Ideally, use Java 8's java.time package and parse them as LocalDateTime values
tl;dr
LocalDateTime.parse( // Parse a string lacking any indicator of time zone or offset-from-UTC into a `LocalDateTime` object.
"201710010200" , // Parse string in “basic” ISO 8601 format.
DateTimeFormatter.ofPattern( "uuuuMMddHHmm" ) // Define a formatting pattern to match the input. If you used expanded ISO 8601 format instead of “basic” you would not need to bother with this step.
).atZone( // Place the inexact unzoned value (`LocalDateTime` object) into the context of a time zone. Produces a `ZonedDateTime` object.
ZoneId.of( "Australia/Sydney" )
).toString() // Generate a string in standard expanded ISO 8601 format. This class extends the standard to wisely append the name of the zone in square brackets.
2017-10-01T03:00+11:00[Australia/Sydney]
If that time-of-day on that date in than zone is invalid, ZonedDateTime class adjusts.
If you fear faulty input, trap for DateTimeParseException.
Details
The Answer by Jon Skeet is correct. Per his comment: There is no instant in time which had a local time of 2am on October 1st 2017 in Sydney.
java.time
The modern solution is the java.time classes that supplant the troublesome old legacy date-time classes.
Parsing
Define a formatting pattern to match your input.
String input = "201710010200" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMddHHmm" ) ;
LocalDateTime
Your input lacks an indicator of offset-from-UTC or time zone. So parse as a LocalDateTime.
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
ldt.toString(): 2017-10-01T02:00
Without the context of a time zone or offset-from-UTC, this value has no real meaning. It does not represent a moment, a point on the timeline. It is only a vague idea about possible moments over a range of about 26-27 hours.
To determine a moment, we need to place this value within the context of a time zone or offset.
You claim to know that value was intended to represent a moment in Australia/Sydney time zone.
ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
2017-10-01T03:00+11:00[Australia/Sydney]
The result is 3 AM. The offset-from-UTC used by the people of that region changed on that date at that time, a cut-over in Daylight Saving Time (DST) silliness. When the clock in that part of Australia was about to strike 2 AM, the clock jumped to 3 AM. The 2 AM hour never existed in that land. The ZonedDateTime class has a policy for automatically adjusting such invalid moment. Be sure to read the doc to see if you understand enter link description hereand agree with its algorithm.
Because this wall-clock time never existed, I suspect you are incorrect about that log data representing a moment in the zone of Australia/Sydney.
UTC
The bigger solution here is to learn to think, work, log, and exchange data all in UTC. Consider UTC to be the One True Time, and all other zones are but a mere variation of that theme. Forget about your own parochial time zone while at work programming/administrating.
In java.time, the basic class for UTC values is 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).
This class can capture the current moment in UTC.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
ISO 8601
The Instant class also can parse/generate strings in standard ISO 8601 format.
String output = Instant.now().toString() ;
"2018-01-23T12:34:56.734591Z"
The Z on the end is short for Zulu and means UTC. This is the crux of your original problem: You stored date-time values without such an indicator of zone/offset.
Parsing:
Instant instant = Instant.parse( "2018-01-23T12:34:56.734591Z" )
I strongly recommending using the ISO 8601 formats for all such storage/exchange of textual date-time values. Be sure to:
include offset/zone when storing/exchanging moments, precise points on the timeline.
Use expanded formats, rather than these “basic” formats that minimize the use of delimiters. These are hard to read by humans, less obvious as to the type of information, and are not used by default in java.time. The java.time classes use the expanded formats by 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.
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.

Convert UTC time to local time zone

I have to convert UTC time into user local time zone. Currently, I have the two parameters one is time in long format and another is time zone name in string format like "(UTC-05:00) Eastern Time (US and Canada), (UTC-06:00) Central Time (US and Canada)" etc.
So now using these two parameters I have to get date time in string format. I am facing the issue while I am trying to convert the date into a string because the SimpleDateFormat.format(...) will convert the date using its default time zone.
Below are the code portion
public static void main(String[] args)
{
long time = 1490112300000L;
System.out.println("UTC Time "+ convertLongToStringUTC(time));
String EST = "(UTC-05:00) Eastern Time (US and Canada)";
TimeZone timeZone1 = TimeZone.getTimeZone(EST);
System.out.println("EST "+ convertTimeZone(time, timeZone1));
String CST = "(UTC-06:00) Central Time (US and Canada)";
TimeZone timeZone2 = TimeZone.getTimeZone(CST);
System.out.println("CST "+ convertTimeZone(time, timeZone2));
String IST = "IST";
TimeZone timeZone = TimeZone.getTimeZone(IST);
System.out.println("IST "+ convertTimeZone(time, timeZone));
}
public String convertTimeZone(long time, TimeZone timeZone)
{
Date date = new Date(time);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
format.setTimeZone(timeZone);
return format.format(date);
}
public String convertLongToStringUTC(long time)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String utcTime = sdf.format(new Date(time));
return utcTime;
}
Also let me know if we can achieve this using offset ?
Use this constructor
SimpleDateFormat(String pattern, Locale locale)
Constructs a SimpleDateFormat using the given pattern and the default
date format symbols for the given locale. Note: This constructor may
not support all locales. For full coverage, use the factory methods in
the DateFormat class.
Java Doc
tl;dr
Instant.ofEpochMilli( 1_490_112_300_000L )
.atOffset( ZoneOffset.of( "-05:00" ) )
Instant.ofEpochMilli( 1_490_112_300_000L )
.atZone( ZoneId.of( "America/New_York" ) )
Details
The Answer by Dennis is close. I will provide further information.
Your Question is not exactly clear about the inputs. I will assume your long integer number represents a moment in UTC.
An offset-from-UTC is an number of hours and minutes and seconds before or after UTC. In java.time, we represent that with a ZoneOffset.
While ZoneId technically works (as seen in code by Dennis), that is misleading as a zone is much more than an offset. A zone is a region’s history of various offsets that were in effect at different periods of history. A zone also includes any planned future changes such as DST cutovers coming in the next months.
ZoneOffset offset = ZoneOffset.of( 5 , 30 ); // Five-and-a-half hours ahead of UTC.
ZoneOffset offset = ZoneOffset.of( "+05:30" );
Tip: Always include the padding zero on the hours. While not always required in various protocols such as ISO 8601, I have seen software systems burp when encountering single-digit hours like +5:00.
If you know the intended time zone for certain, use it. A zone is always better than a mere offset as it brings all that historical information of other offsets for the past, present, and future.
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( "Asia/Kolkata" );
I am guessing your number is a number of milliseconds since the epoch of 1970-01-01T00:00:00Z.
Instant instant = Instant.ofEpochMilli( 1_490_112_300_000L );
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).
You can adjust into a time zone.
ZonedDateTime zdt = instant.atZone( z );
These issues have been covered many times in Stack Overflow. Hence the down-votes you are collecting (I am guessing). Please search Stack Overflow thoroughly before posting.
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.
Where to obtain the java.time classes?
Java SE 8 and 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 SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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.
Using Java 8 you can do
OffsetDateTime dt = Instant.ofEpochMilli(System.currentTimeMillis())
.atOffset( ZoneOffset.of("-05:00"));
//In zone id you put the string of the offset you want

How come new Date(0L) doesn't return zero date

Date date = new Date(0L);
Shouldn't it give me a zero date? Like 00/00/0000? Gives me Wed Dec 31 19:00:00 EST 1969
Per the javadocs, this constructor on Date uses an offset from baseline time:
Allocates a Date object and
initializes it to represent the
specified number of milliseconds since
the standard base time known as "the
epoch", namely January 1, 1970,
00:00:00 GMT.
Presumably you are on EST, hence the result.
As an aside, I would not expect the result you noted to be produced by any conceivable Date manipulation, since that's not even a valid date (month and day = 0).
From the Java API:
Date(long date): Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
See: http://download.oracle.com/javase/1.4.2/docs/api/java/util/Date.html
The time is milliseconds since the epoch.
The epoch is 1/1/1970 GMT.
Because that constructor creates the object initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
Java dates, and most computer implementation of dates, are stored as milliseconds of seconds starting from what's called the epoch. That is 1 January, 1970. Java date is represented as milliseconds since epoch. and 0 milliseconds since epoch is the epoch itself. And that's why you get that value.
tl;dr
First moment of 1970 in UTC:
Instant.EPOCH.toString()
1970-01-01T00:00:00Z
And the same moment as seen in New York region:
Instant.EPOCH.atZone( ZoneId.of( "America/New_York" ) ).toString()
1969-12-31T19:00-05:00[America/New_York]
Details
The other Answers are correct: The epoch reference is first moment of 1970 in UTC while your time zone is 5 hours behind UTC. Here's updated info.
java.time
The modern approach uses java.time classes that supplanted the troublesome old legacy date-time classes.
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).
The epoch reference of 1970-01-01T00:00:00Z is defined as a constant, Instant.EPOCH.
Instant.EPOCH.toString()
1970-01-01T00:00:00Z
To see that same moment in another time zone, apply a ZoneId to get a ZonedDateTime. You can think of it as: “ZonedDateTime = Instant + ZoneId”.
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( "America/New_York" ) ;
ZonedDateTime zdt = Instant.EPOCH.atZone( z ) ;
zdt.toString(): 1969-12-31T19:00-05:00[America/New_York]
The result is a time-of-day five hours earlier, on last day of previous year. This ZonedDateTime represents the same moment, the same simultaneous point on the timeline, but a different wall-clock time.
That same moment in India is five and a half hours ahead of UTC rather than behind.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = Instant.EPOCH.atZone( z ) ;
System.out.println(zdt );
zdt.toString(): 1970-01-01T05:30+05:30[Asia/Kolkata]
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.
With a JDBC driver complying with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings or 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.

Categories