JAVA TimeZone issue EDT Vs EST
I don't think you should do what you are suggesting.
You are saying that regardless of what your system timezone is currently (Eastern Time is NOT your time zone, but UTC+5 or +4 is), you want it to display EST. This is just plainly wrong. Suppose it's in the summer, and your computer thinks it's 2010/6/15 15:00 locally. You print the current time and you get:
The time I print this out at: 2010 06 15 15:00:00 EDT
For whatever reason, you think that the EDT is unpleasing, and so you change it to EST:
I print this out at: 2010 06 15 15:00:00 EST
however, if you then send that snippet to someone else within the next hour, they'll be forced to think you traveled from the future! Since 15:00:00 EST is 16:00:00 EDT.
I would create a custom zone:
TimeZone alwaysEst = TimeZone.getTimeZone("EST+5");
That will report as EST and will always be 5 hours ahead of UTC. In particular, do not choose an existing timezone or you will eventually get burned when a zone update changes the definition.
Do be aware that by forcing EST the dates you log will only match the time displayed by the system for 5 months out of the year. The other 7 months you'll be an hour off. It may simplify parsing the file, but it will confuse users.
Date-time work is tricky
I a newbie to java and hence haven't been able figure this out since quite some time.
Date-time handling is surprisingly tricky for even experienced programmers. The concepts are rather slippery. All kinds of practices have developed by various people in various industries, thereby complicating matters.
Fortunately, Java now has built-in the industry-leading framework for date-time work: java.time defined in JSR 310.
Explicitly specify desired/expected time zone
I am using Windows XP and the machine is set to TimeZone:
The host OS should not affect your date-time handling work in Java.
Never rely on the host machine's current default time zone. That default can change at any time, so it is outside your control as a programmer. Instead, specify your desired/expected time zone within your Java code.
ZoneId z = ZoneId.of( "America/New_York" ) ;
EDT
/ Eastern Time
is not a time zone
… Eastern Time (US & Canada).
There is not really such a thing as "Eastern Time". This imprecise term is a grab-bag collective noun used to describe the current offset-from-UTC used by various time zones. When doing programming, forget all about "Eastern Time", "EST", and other pseudo-zones.
Offset versus zone
Understand that an offset is merely a number of hours-minutes-seconds ahead or behind the prime meridian. An offset looks like +05:30
or -05:00
.
A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region. The rules of a time zone are set capriciously by politicians, and change with surprising frequency.
A proper time zone name is composed as Continent/Region
such as America/Montreal
or America/New_York
. See this list of zones at Wikipedia (may not be up-to-date).
ISO 8601
writes a string like: 20101012 15:56:00 EST, to a file.
We have a formal international standard for the formats of date-time values being serialized as text: ISO 8601. Do not invent your own! The standard formats are wisely designed to be practical, easy to parse by machine, and easy to read by humans across cultures.
For example, nearly 4 PM on the twelveth of October in 2010 in Québec would be:
2010-10-12T15:56-04:00
The java.time classes use the ISO 8601 formats by default when parsing/generating text. So no need to specify a formatting pattern. Use ZonedDateTime
to represent a moment as seen through a particular time zone.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2010 , 10 , 12 , 15 , 56 , 0 , 0 , z ) ;
The ZonedDateTime::toString
method wisely extends the standard format to append the name of the zone in square brackets.
zdt.toString(): 2010-10-12T15:56-04:00[America/Montreal]
Parsing such a string.
ZonedDateTime zdt2 = ZonedDateTime.parse( "2010-10-12T15:56-04:00[America/Montreal]" ) ;
boolean sameZdts = zdt.equals ( zdt2 ) ;
sameZdts: true
See that code run live at IdeOne.com.
Daylight Saving Time (DST)
EST is what I want ALWAYS and not EDT.
Your goal does not make sense.
Those pseudo-zones (EST
& EDT
) are meant to indicate when Daylight Saving Time (DST) is in effect and when standard time is in effect. So wanting to always be using standard time in a region (a time zone) that observes DST is a contradiction, and not possible.
So if you are trying to represent a moment as seen through the wall-clock time used by the people of a particular region (a time zone), you should specify the date, the time-of-day, and the time zone via ZoneId
, and let java.time handle the issue of whether DST is in effect or not.
LocalDate ld = LocalDate.of( 2010 , Month.OCTOBER , 12 ) ;
LocalTime lt = LocalTime.of( 15 , 56 , 0 ) ;
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
zdt.toString(): 2010-10-12T15:56-04:00[America/New_York]
To see that same moment in UTC, extract an Instant
. Same moment, same point on the timeline, different wall-clock-time.
Instant instant = zdt.toInstant() ;
instant.toString(): 2010-10-12T19:56:00Z
See that code above run live at IdeOne.com.
Booking future appointment
am dealing with a server to whom I need to tell: "Do a task at 20101015 15:30:30 xxx" xxx being the timezone. The server understands only EST and not EDT whatever month it is. Hence, EDT is unpleasing.
Regarding the EST versus EDT, we already covered your concern as senseless/irrelevant. These flags for standard time versus Daylight Saving Time automatically switch over when a particular time zone cuts over to/from DST.
As for booking an appointment in the future, you cannot know if Daylight Saving Time (DST) is in effect or not. You cannot know if some other wacky adjustment has been made to the rules of your time zone.
As mentioned above, time zone definitions are controlled by capricious politicians. Around the world, they have shown a surprising penchant for frequent changes. The US has changed the dates of their DST cutovers multiple times over the decades. Russia has adopted and dropped DST multiple times in recent years. The latest fad is to stay on DST year-round, done recently by Turkey and Morocco, and the United States is on the verge of going this way as well.
So if you want an appointment or a task to be done at a certain time-of-day, you have represent that as a LocalDateTime
which represents a date and time-of-day without the context of an offset/zone, plus represent separately the intended time zone (ZoneId
).
LocalDate ld = LocalDate.of( 2020 , Month.MARCH , 15 ) ;
LocalTime lt = LocalTime.of( 15 , 0 ) ;
LocalDateTime ldt = LocalDateTime.of( ld , lt ) ;
ZoneId z = ZoneId.of( "America/Thunder_Bay" ) ;
That code above describes when we intend something to occur, but cannot determine a moment. We do not know when 3 PM will happen on March 15, because the politicians controlling the America/Thunder_Bay
time zone may redefine the time zone at any moment. So all we can do is occasionally take a stab at it, dynamically. When you need to build a calendar, or schedule something to occur, you must apply the time zone to the LocalDateTime
(not a moment) to produce a ZonedDateTime
(a moment).
ZonedDateTime zdt = ZonedDateTime.of( ldt , z ) ;
Instant instant = zdt.toInstant() ; // Adjust from zone to UTC (an offset of zero). Same moment, same point on the timeline.
Executors
To schedule your task to run, learn about the Executors framework built into Java. Specifically, the ScheduledExecutorService
class.
Firs calculate your elapsed time to wait until running the task.
Duration duration = Duration.between( Instant.now() , instant );
Define the task to be run as a Runnable
. Here we use modern lambda syntax, but that is beside the point.
Runnable runnable = ( ) -> {
System.out.println( "Running our task now: " + Instant.now() );
};
Schedule your task to run. Optionally capture the returned ScheduledFuture
if you want to track completion.
final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture future = scheduler.schedule( runnable , duration.toMinutes() , TimeUnit.MINUTES );
Important: Be sure to gracefully shutdown your ScheduledExecutorService
. Otherwise, the thread pool may continue running, even after you end your program.