Printing GMT and PST timestamp shows a difference of only 7 hours - java

My understanding is that PST differs from GMT / UTC by 8 hours. However, when I print this out, I find only a difference of 7 hours. Can you explain what I have done incorrectly here?
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
Date date = sdf1.parse("2014-05-01 13:31:03.7");
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd_HHmmssS");
df.setTimeZone(TimeZone.getTimeZone("PST"));
System.out.println(df.format(date));
df.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(df.format(date));
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(df.format(date));
Prints:
20140501_1331037
20140501_2031037
20140501_2031037

I assume you are doing PST in summer/daylights saving time when it is GMT+7. Try the middle of winter.
From http://wwp.greenwichmeantime.co.uk/time-zone/usa/pacific-time/
When does Pacific Time change to Daylight Saving Time?
In most states
in the USA and in most provinces in Canada, Daylight-Saving Time (DST)
is observed. During DST PT or PDT is 7 hours behind Greenwich Mean
Time (GMT-7).
After the Summer months Pacific Time is shifted back by 1 hour to US
Pacific Standard Time (PST) or (GMT-8).
The schedule for the states of the United States that adopt daylight
saving time are:
2 a.m. on the Second Sunday in March to
2 a.m. on the First Sunday of
November.

You have not done anything incorrectly here. If you add the timezone in to the output format:
SimpleDateFormat df = new SimpleDateFormat("HH mm ssS Z z");
you can see the output is actually PDT (daylight savings) and not PST (regular)
10 31 037 -0700 PDT
17 31 037 +0000 GMT
17 31 037 +0000 UTC
12 31 037 -0500 EST
17 31 037 +0000 GMT
May is in Daylight saving time.

Here is the solution using Joda-Time 2.6.
String inputRaw = "2014-05-01 13:31:03.7";
String input = inputRaw.replace( " ", "T" ); // Adjust input to comply with the ISO 8601 standard.
DateTimeZone zone = DateTimeZone.UTC;
DateTime dateTime = new DateTime( input, zone ); // The input lacks an offset. So specify the time zone by which to interpret the parsed input string. The resulting DateTime is then adjusted to the JVM’s current default time zone. So, *two* time zones were used in this line of code, one explicit, the other implicit.
DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC ); // Adjust to UTC.
DateTime dateTimeLosAngeles = dateTime.withZone( DateTimeZone.forID( "America/Los_Angeles" ) ); // Adjust to US west coast time zone. DST is automatically applied as needed.
DateTime dateTimeKolkata = dateTime.withZone( DateTimeZone.forID( "Asia/Kolkata" ) ); // Adjust to India time, five and a half hours ahead of UTC.
All of these DateTime objects represent the same moment in the timeline of the history of the universe. Each has a different time-of-day (and possibly different date) to suit the "wall time" on clocks as likely seen by people in a particular locality.

Related

Date format conversion from CST to GMT is not working

I have a date string in CST (24 Hours) and I want to convert it to GMT (12 Hours).
I have a java method like below which works fine when my system time is Kolkata time. (System where I run the java method)
But when my system is in Shanghai time, the GMT time comes incorrect.
String inputDate = "01-19-2017 06:01 CST";
SimpleDateFormat inputFormatter = new SimpleDateFormat("MM-dd-yyyy hh:mm Z");
parsedInput = inputFormatter.parse(inputDate);
// parsedInput -> Tue Jan 19 06:01:00 CST 2017 -> When system time is Shanghai time
// parsedInput -> Thu Jan 19 17:31:00 IST 2017 -> When system time is Kolkata time
SimpleDateFormat formatter = new SimpleDateFormat("MM-dd-yyyy hh:mm a Z");
TimeZone gmt = TimeZone.getTimeZone("GMT");
formatter.setTimeZone(gmt);
String formattedDate = formatter.format(parsedInput);
// formattedDate -> 01-18-2017 10:01 PM +0000 -> When system time is Shanghai time (Incorrect)
// formattedDate -> 01-19-2017 12:01 PM +0000 -> When system time is Kolkata time
Avoid pseudo time zones
The 3-4 letter time zone abbreviations such as CST are not actual time zones. They are not standardized. They are not even unique!
Your CST might be “China Standard Time” or might be “Central Standard Time” in the Americas, or might be something else. There is no way to know which one.
Another example: IST might mean “India Standard Time” or “Ireland Standard Time” or others.
Deciphering these pseudo-zones reliably is impossible. The Joda-Time library has a wise policy of refusing to even try. Unfortunately the java.time classes make a guess when parsing, but the result may not be the zone you expect.
So never use these useless pseudo-zones. Use a proper time zone name in the format of continent/region such as America/Chicago, Asia/Kolkata, Pacific/Auckland.
Avoid legacy date-time classes
You are using the troublesome old date-time classes that are now legacy, supplanted by the java.time classes.
Workaround
If you know all your inputs are intended for the same time zone, then lop off the pseudo-zone and process as a LocalDateTime, apply the intended zone as a ZoneId to produce a ZonedDateDate. From that you can extract an Instant for UTC time.
String input = "01-19-2017 06:01".replace( " " , "T" ) ; // Insert a “T” to comply with standard ISO 8601 format used by default in java.time.
LocalDateTime ldt = LocalDateTime.parse( input ); // Lacks any concept of time zone or offset-from-UTC. So *not* an actual moment on the timeline.
ZoneId z = ZoneId.of( "America/Chicago" ); // Assuming “CST” meant this zone in North America.
ZonedDateTime zdt = ldt.atZone( z ); // Assign a time zone to determine an actual moment on the timeline.
Instant instant = zdt.toInstant(); // Extract a value in UTC.
You may choose to see that same moment through the lens of the wall-clock time in India.
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant( ZoneId.of( "Asia/Kolkata" ) ) ;
Never rely on default zone
Your JVM’s current default time zone can be changed at any moment by any code in any thread of any app executing within that JVM. Since this can change at any moment you cannot rely on a certain value.
When you omit the optional argument for time zone, the date-time classes implicitly silently apply the current default time zone. So the solution is simple: Always specify the expected/desired time zone.
Notice how the code example above specifies the zone at every opportunity.
(Ditto for Locale, by the way. Specify explicitly rather than rely on current default.)
Your problem is the ambiguity of CST. In most cases SimpleDateFormat understands CST as Central Standard Time as you had expected. But when your computer is running Shanghai Time, this becomes the time zone of the formatter’s calendar, and then it suddenly understands CST as China Standard Time, the same as Shanghai time.
Therefore Darshan Mehta’s solution, setting inputFormatter’s time zone to something other than China Standard Time, works on my computer. I don’t know why it didn’t work on yours (I set it to TimeZone.getTimeZone("America/Chicago") to match the intended interpretation of CST).
The correct and good solution, though, is to avoid the three and four letter time zone abbreviations completely. Yours is just one example out of many where they cause trouble. If you can, give your input string with an explicit zone offset from UTC, such is never ambiguous:
String inputDate = "01-19-2017 06:01 -0600";
Now your code works as expected no matter your computer’s time zone setting. The Z in the pattern string you already have matches -0600 nicely.
All of this said, if you can use the Java 8 date and time classes, you can do yourself a favour of switching over to them. I hesitate to call them “Java 8 date and time classes” because they have also been backported to Java 6 and 7, so if you can live with a library dependency until you get to Java 8, you should have every chance. The newer classes are significantly more programmer-friendly and convenient to work with. A simple example to get you started:
String inputDate = "01-19-2017 06:01 -0600";
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm Z");
ZonedDateTime parsedInput = ZonedDateTime.parse(inputDate, inputFormatter);
OffsetDateTime gmtTime = parsedInput.toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy hh:mm a Z");
String formattedDate = gmtTime.format(formatter);
System.out.println(formattedDate); // prints 01-19-2017 12:01 PM +0000
Try setting the TimeZone to inputFormatter as well, e.g.:
SimpleDateFormat inputFormatter = new SimpleDateFormat("MM-dd-yyyy hh:mm Z");
inputFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
If you don't specify the time zone, it takes the default value into account which is Asia/Shanghai in your case and hence, incorrect result.
You can reproduce it in your current system by replacing GMT with Asia/Shanghai in the above snippett

Why does SimpleDateFormat.format(Date) ignore the configured TimeZone?

Given that my default TimeZone is Europe/Paris:
System.out.println("Current Timezone: " + TimeZone.getDefault());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
String dateStrIn = "2016-08-01T00:00:00Z";
Date date = dateFormat.parse(dateStrIn);
String dateStrOut = dateFormat.format(date);
System.out.println("Input date String: "+dateStrIn);
System.out.println("Date.toString() "+date);
System.out.println("Output date String: "+dateStrOut);
The output is:
Current Timezone: sun.util.calendar.ZoneInfo[id="Europe/Paris",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=184,lastRule=java.util.SimpleTimeZone[id=Europe/Paris,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]
Input date String: 2016-08-01T00:00:00Z
Date.toString() Mon Aug 01 02:00:00 CEST 2016
Output date String: 2016-08-01T02:00:00+02
Now, I repeat the execution but setting a different default TimeZone (UTC):
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
System.out.println("Current Timezone: " + TimeZone.getDefault());
...
And this is the output:
Current Timezone: sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
Input date String: 2016-08-01T00:00:00Z
Date.toString() Mon Aug 01 00:00:00 UTC 2016
Output date String: 2016-08-01T02:00:00+02
Date.toString() has correctly taken into account the TimeZone change. However, the String gotten from dateFormat.format(date); is still showing +02 instead of Z or +00, why?
Using standard Java API, is there any way to force the formatting according to a selected TimeZone?
UPDATE:
Jesper's solution works in almost all cases, but I have come across this one (using Canary Island's summer time zone WEST) in which it doesn't:
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss z");
dateFormat.setTimeZone(TimeZone.getTimeZone("Europe/Paris"));
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Paris"));
System.out.println("Current Timezone: " + TimeZone.getDefault());
String dateStrIn = "2016-08-01T08:00:00 WEST";
Date date = dateFormat.parse(dateStrIn);
String dateStrOut = dateFormat.format(date);
System.out.println("Input date String: "+dateStrIn);
System.out.println("Date.toString() "+date);
System.out.println("Output date String: "+dateStrOut);
Output:
Current Timezone: sun.util.calendar.ZoneInfo[id="Europe/Paris",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=184,lastRule=java.util.SimpleTimeZone[id=Europe/Paris,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]
Input date String: 2016-08-01T08:00:00 WEST
Date.toString() Mon Aug 01 09:00:00 CEST 2016
Output date String: 2016-08-01T08:00:00 WEST
You can see that Output date String is still expressed in WEST.
If, for instance, I change the initial dateStrIn to: String dateStrIn = "2016-08-01T08:00:00 GMT";, then the Output date String is expressed in CEST as espected:
Output date String: 2016-08-01T10:00:00 CEST
Could it be a bug?
UPDATE 2:
Another example
Default TimeZone for both Date and SimpleDateFormat: "Europe/Paris"
Input String: "2016-08-01T08:00:00 WET"
Output:
Date.toString() Mon Aug 01 10:00:00 CEST 2016
Output date String: 2016-08-01T09:00:00 WEST
Notice that dateFormat.format(date); has produced a WEST date string. From WET -> WEST when it should be WET -> CEST.
Instead of setting the default time zone, set the time zone on your SimpleDateFormat object:
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
This will make the SimpleDateFormat object format your Date object in the UTC time zone.
If you're using Java 8, consider using the new date and time API in the package java.time instead of the old java.util.Date and java.text.SimpleDateFormat.
You torture yourself by using the troublesome old legacy date-time classes now outmoded by the java.time framework.
tl;dr
ZonedDateTime.ofInstant( Instant.parse( "2016-08-01T00:00:00Z" ) , ZoneId.of( "Europe/Paris" ) )
java.time
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat. The Joda-Time team also advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
Instant
The Z on the end of your input string 2016-08-01T00:00:00Z is short for Zulu and means UTC. Represented in java.time by the Instant class with a resolution up to nanoseconds.
Instant instant = Instant.parse ( "2016-08-01T00:00:00Z" );
ZonedDateTime
Specify a time zone via ZoneId to get a ZonedDateTime.
In the summer, Paris time is two hours ahead of UTC. So the same moment as seen on a clock on the wall in Paris is 2 AM rather than midnight, on same date of August 1st.
ZoneId zoneId_Paris = ZoneId.of ( "Europe/Paris" );
ZonedDateTime zdt_Paris = ZonedDateTime.ofInstant ( instant , zoneId_Paris );
You can adjust into another time zone such as Atlantic/Canary. For this date in the summer, the time is one hour ahead of UTC. Result is 1 AM rather than midnight.
ZoneId zoneId_Canary = ZoneId.of ( "Atlantic/Canary" );
ZonedDateTime zdt_Canary = zdt_Paris.withZoneSameInstant ( zoneId_Canary );
Dump to console.
System.out.println ( "instant: " + instant + " | zdt_Paris: " + zdt_Paris + " | zdt_Canary: " + zdt_Canary );
instant: 2016-08-01T00:00:00Z | zdt_Paris: 2016-08-01T02:00+02:00[Europe/Paris] | zdt_Canary: 2016-08-01T01:00+01:00[Atlantic/Canary]
All three of these objects (UTC, Paris, Canary) represent the very same simultaneous moment in history, the same single point on the timeline. Each is viewed through the lens of a different wall-clock time.
Real Time Zones
Avoid 3-4 letter zone abbreviations such as WET and WEST. These are not real time zones, not standardized, and not even unique(!).
Europe/Paris and Atlantic/Canary are proper time zone names, in the format of continent/region.
The answer to this mystery was on the Javadoc:
DateFormat.parse(String source, ParsePosition pos)
This parsing operation uses the calendar to produce a Date. As a
result, the calendar's date-time fields and the TimeZone value may
have been overwritten, depending on subclass implementations. Any
TimeZone value that has previously been set by a call to setTimeZone
may need to be restored for further operations.
Setting the TimeZone after parsing works it out:
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss z");
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Paris"));
System.out.println("Current Timezone: " + TimeZone.getDefault());
String dateStrIn = "2016-08-01T08:00:00 WET";
Date date = dateFormat.parse(dateStrIn);
dateFormat.setTimeZone(TimeZone.getTimeZone("Europe/Paris"));
String dateStrOut = dateFormat.format(date);
System.out.println("Input date String: "+dateStrIn);
System.out.println("Date.toString() "+date);
System.out.println("Output date String: "+dateStrOut);
Right output:
Current Timezone: sun.util.calendar.ZoneInfo[id="Europe/Paris",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=184,lastRule=java.util.SimpleTimeZone[id=Europe/Paris,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]
Input date String: 2016-08-01T08:00:00 WET
Date.toString() Mon Aug 01 10:00:00 CEST 2016
Output date String: 2016-08-01T10:00:00 CEST
No, its not a bug.
You have to first understand how Date class works. It is nothing but a wrapper over the number of milliseconds since the epoch, expressed in long. Hence, whichever timezone it may be, the underlying value of the date object remains the same. You can never really change the timezone of a Date class. You can only represent a String format of a date instance using a SimpleDateFormat class. This representation might have different time zones, based on which you are using while creating the SimpleDateFormatobject.
Again, you need to check the toString method of the Date class. It always prints the date with the default time zone.
Edit
You should look at the SimpleDateFormat.parse() definition as well. The JDK says that,
The TimeZone value may be overwritten, depending on the given pattern and the time zone value in text. Any TimeZone value that has previously been set by a call to setTimeZone may need to be restored for further operations.

Dateformat converting IST to GMT

Problem in converting IST to GMT.
DateFormat df = new SimpleDateFormat("HH:mm:ss z");
String input = "05:30:00 IST";
Date d = df.parse(input);
Calendar c = Calendar.getInstance();
c.setTime(d);
System.out.println(c.getTime());
getting Thu Jan 01 03:30:00 GMT 1970 as output instead of Thu Jan 01 00:00:00 GMT 1970
You should be wary of using three-letter abbreviations of timezones because they are ambiguous. In this case, IST could refer to:
Indian Standard Time (UTC+0530)
Israel Standard Time (UTC+02)
Irish Standard Time (UTC+01)
Wikipedia lists some common timezone abbreviations; examples of other ambiguous common abbreviations are:
AM(S)T
AST
BST
CDT
CST
ECT
FKST
GST
MST
It is better to use either a UTC offset (e.g. +0530 for Indian Standard Time) or a uniquely-defined timezone identifier (e.g. Asia/Calcutta)
There are a number of things wrong with what you seem to be trying to do here.
You are trying to use a java.util.Date object to contain just a time-of-day (hours, minutes, seconds). A java.util.Date object is not suitable for that purpose. A java.util.Date object is really a timestamp - it represents an "absolute" moment in time, counted as a number of milliseconds since 01-01-1970, 00:00:00 GMT.
A java.util.Date object does not contain timezone information. You cannot convert a Date object from one timezone to another timezone, because the Date object simply does not contain information about a timezone.
Converting a time-of-day from one timezone to another cannot be done if you only know the hours, minutes and seconds. The result also depends on the date (year, month, day) - the results can be influenced by daylight savings transitions. So it's not possible to convert a time-of-day from one timezone to another if you don't know the date.
If you use the Java 8 java.time API, then it's easy; use ZonedDateTime, which does contain information about the timezone.
// Assuming that with "IST" you mean India Standard Time
ZonedDateTime input = ZonedDateTime.of(2015, 3, 23, 5, 30, 0, 0, ZoneId.of("Asia/Calcutta"));
System.out.println(input);
ZonedDateTime output = input.withZoneSameInstant(ZoneId.of("GMT"));
System.out.println(output);
If you want to use the old java.util.Date and java.util.Calendar API, then you set the timezone on the DateFormat object that you use to display the date - not on the Date object itself:
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
cal.set(2015, Calendar.MARCH, 23, 5, 30, 0);
Date input = cal.getTime();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
System.out.println(df.format(input));
df.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(df.format(input));

Java: Convert MST to EST

I've been trying to convert the time since epoch until today and display it in Eastern Standard Time. Here is what outputs on the remote machine (it's remotely hosted):
Date now = new Date(System.currentTimeMillis());
System.out.println(now.toString());
// Thu Apr 24 14:36:11 MST 2014
No idea what MST is, but I want to get the current milliseconds since epoch in EST, and display the result in EST.
No matter what I do, I can't get daylights savings to work (it's currently Daylights Savings Time in the EST Time Zone); I either end up in PST, GMT or UTC, and when I do get "EST" it's either some random value or 1 hour behind or 3 hours behind.
I would like the output to be formatted using this DateFormat:
DateFormat EXPIRE_FORMAT = new SimpleDateFormat("MMM dd, yyyy h:mm a z");
Just set the time zone you want the time to be displayed in using DateFormat#setTimeZone(TimeZone)
Date now = new Date(System.currentTimeMillis());
DateFormat EXPIRE_FORMAT = new SimpleDateFormat("MMM dd, yyyy h:mm a z");
EXPIRE_FORMAT.setTimeZone(TimeZone.getTimeZone("America/Montreal")); // or whatever relevant TimeZone id
System.out.println(EXPIRE_FORMAT.format(now));
AFAIK, there is no EST currently. It's all EDT in Spring.
The above prints
Apr 24, 2014 5:53 PM EDT
The comments and the answer by Sotirios Delimanolis are correct.
Avoid 3 or 4 Letter Time Zone Codes
You should avoid the 3 or 4 letter codes for time zones as they are neither standardized nor unique. Instead use proper time zone names, usually a continent+city.
Avoid j.u.Date
The java.util.Date and .Calendar & SimpleDateFormat classes bundled with Java are notoriously troublesome. Use a decent date-time library with an updated time zone database. For Java, that means either Joda-Time or the new java.time package in Java 8 (inspired by Joda-Time).
Avoid Milliseconds-Since-Epoch
I suggest you avoid working with milliseconds since epoch. Gets confusing fast as the number is meaningless when read by a human. Let the date-time library manage the milliseconds for you.
Specify Time Zone
Generally best to specify the desired/intended time zone. If you omit the time zone, all the major date-time libraries (java.util.Date, Joda-Time, java.time) apply the JVM's default time zone.
Joda-Time Example
Example code in Joda-Time 2.3.
DateTimeZone timeZoneToronto = DateTimeZone.forID( "America/Toronto" );
DateTime dateTimeToronto = new DateTime( timeZoneToronto ); // Current moment.
DateTime dateTimeUTC = dateTimeToronto.withZone( DateTimeZone.UTC );
DateTime dateTimeParis = dateTimeToronto.withZone( DateTimeZone.forID( "Europe/Paris" ) );
If you really want the milliseconds since epoch, call the getMillis method. In example code above, all three DateTime objects have the same number of milliseconds-since-epoch.
long millis = dateTimeToronto.getMillis();
If you need a java.util.Date for use with other classes…
java.util.Date date = dateTimeToronto.toDate();
While Joda-Time uses the ISO 8601 standard formats as its defaults, you may specify other formats for generating strings.
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MMM dd, yyyy h:mm a z" );
String output = formatter.print( dateTimeToronto );

Java Date (Calendar) calculating the start of a day in local time given a date time

All,
Having a hard day in the office with this one... I am trying to workout the start of a day in Local Time, i.e. Midnight 00:00:00, given any calendar date.
Given the following days, I want to calculate the start of the day at local time midnight:
Time Start Day (Local) Start Day (GMT)
2011-03-27 00:00:00 GMT --> 2011-03-27 00:00:00 GMT --> 2011-03-27 00:00:00 GMT
2011-03-27 01:00:00 GMT --> 2011-03-27 00:00:00 GMT --> 2011-03-27 00:00:00 GMT
2011-03-27 02:00:00 GMT --> 2011-03-27 00:00:00 GMT --> 2011-03-27 00:00:00 GMT
2011-04-01 00:00:00 BST --> 2011-04-01 00:00:00 BST --> 2011-03-31 23:00:00 GMT
2011-10-30 00:00:00 BST --> 2011-10-30 00:00:00 BST --> 2011-10-29 23:00:00 GMT
2011-10-30 01:00:00 BST --> 2011-10-30 00:00:00 BST --> 2011-10-29 23:00:00 GMT
2011-10-30 01:00:00 GMT --> 2011-10-30 00:00:00 BST --> 2011-10-29 23:00:00 GMT
2011-11-01 00:00:00 GMT --> 2011-11-01 00:00:00 GMT --> 2011-11-01 00:00:00 GMT
At present, I am parsing the String Time into a GregorianCalendar using a SimpleDateFormat. This gives me the GMT/UTC time to calculate from.
So I have some code which parses the string into a GregorianCalendar:
public GregorianCalendar getCalendar(String dateTime) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(sdf.parse(dateTime, new ParsePosition(0)));
return cal;
}
Now I need to set it to midnight locally:
public void setToStartOfDayLocally(GregorianCalendar cal) {
????
}
I am not too sure what I need to do at the minute with the Calendar. Unfortunately we are not moving to JODA date in the near future. I am also not accounting for different time zones with my example.
Any thoughts?
Thanks,
Andez
I think this code might solve your issue. I am using it to convert from time in local timezone to another.
public static Date convertLocalDateToDateTimezone( Date localDate, String timezone ) {
TimeZone localTimeZone = TimeZone.getDefault();
TimeZone timezone = TimeZone.getTimeZone( timezone );
long gmtMillis = localDate.getTime();
long result = gmtMillis + timezone.getOffset( gmtMillis ) - localTimeZone.getOffset( gmtMillis );
return new Date( result );
}
Hope this helps.
It sounds like you just want to set all of the time parts to zero. You can use:
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
(Assuming you've got the time zone in the calendar set properly.)
Note that that isn't necessarily valid though - in some time zones (e.g. Brazil), at a daylight saving transition midnight either occurs twice or not at all.
Personally I'd start making noises about moving to Joda Time though, which makes all of this a lot simpler :)
java.time
You are using outmoded classes. In Java 8 and later, use built-in java.time framework.
Do not assume the day starts at the time 00:00:00.0. Because of anomalies such as Daylight Saving Time (DST) the start-of-day may vary by time zone. Let the java.time classes determine the correct time with a call to LocalDate::atStartOfDay.
Avoid using 3-4 letter zone abbreviations such as BST, EST, and so on. They are neither standardized nor unique. Use proper time zone names.
An Instant is a moment on the timeline in UTC. Apply a time zone to get a ZonedDateTime. Extract a date-only value from that date-time, a LocalDate. Apply a time zone with a call to atStartOfDay to get back to a ZonedDateTime set to the first moment of the day in that time zone.
Instant now = Instant.now();
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
LocalDate localDate = zdt.toLocalDate();
ZonedDateTime zdtStart = localDate.atStartOfDay( zoneId );
Tip: Avoid the word “midnight”. Does not have a precise definition. Some people think of trying to determine the last moment of the day which is a problem because of an infinitely divisible fraction of a second. Some people think of the the special string “24:00” to indicate the stroke of midnight which further confuses date-time handling. Experience from the Joda-Time project teaches us that it is best to focus on “first moment of the day” as a clear and precise meaning. Also, be aware that the first moment is not always 00:00:00, due to Daylight Saving Time (DST) and other anomalies in some time zones. That is why we depend on the atStartOfDay method rather than hard-code a zero-time-of-day.

Categories