1

I found this funny behavior while using Date and Calendar class to handle Exponential distributions for simulating arrival time at a store (academic work). The code is quite simple and is below displayed. Well suppose that "this.currentDate" is "Feb 15 08:00:00 BRST 2014". If i shift forward the time 24h (parameter iSeconds=86.400), what is supposed to return ? The expected string would be "2014-02-16 08:00:00" but instead the time is shortened in 1h and the result is "2014-02-16 07:00:00", I wonder if someone could explain why my one hour was "stolen". No big deal, but since my next arrival time depends of the earlier one, it makes a mess over my time baseline shifting all of them one hour as well.

I thought could be some TZ issue, but heck, i just moved 24h in the middle of February.

public  String shiftTimeStamp( int iSeconds)
{
 Calendar cal = Calendar.getInstance();     
     cal.setTime(this.currentDate);
     cal.add(Calendar.SECOND, iSeconds);
     this.currentDate = cal.getTime();
     String sTS = new SimpleDateFormat(SCSimLabels.DATE_TS_FORMAT).format(this.currentDate);
return sTS;
}

Note: Daylight Saving Time issue :) BRT <--> BRST tz.

my workaround: I just want a beacon to guide the time jumps caused by inter arrival times and I´m not interested on such calendar specificities, so when I need to move to the first work hour of the next day I just force the time to be 08:00:00 after 1 day shift. It works like a charm :)

Calendar cal = Calendar.getInstance();
cal.setTime(this.currentDate);
cal.add(Calendar.DATE, 1);

String sDate = (new SimpleDateFormat("yyyy-MM-dd 08:00:00")).format(cal.getTime());
Date newDate =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(sDate);   
this.currentDate = newDate;
Giovanni
  • 13
  • 3
  • 1
    maybe summer/winter time? – peter.petrov Dec 04 '13 at 22:19
  • 4
    the BRST part kind of explains that for you. http://en.wikipedia.org/wiki/Bras%C3%ADlia_Summer_Time#Daylight_saving_time -- the middle of February is when it changes over in Brazil. – Mike 'Pomax' Kamermans Dec 04 '13 at 22:20
  • aha, so it seems it is indeed the summer/winter time change causing this – peter.petrov Dec 04 '13 at 22:21
  • If the TZ is constant (BRST both before and after) then this should not happen. The format call must be selecting BRDT time zone based on the date. BRST and BRDT are both internally consistent year-round, although one is selected as the "default" at different times of year. – Tom McClure Dec 04 '13 at 22:25

2 Answers2

0

Change the format call to this:

return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").format(this.currentDate);

To see what timezone the format call is using. I bet the call to .add() is modifying the Calendar object's timezone since it crosses the standard time / daylight time border.

If this is the case, you could try adding a Calendar.DAY,1 or simply .setTimeZone(...) of the Calendar obj. back to the original timezone after the .add call.

Tom McClure
  • 6,699
  • 1
  • 21
  • 21
  • I did as you asked, and here are the results. As can be seen, time zone has changed from BRST to BRT. I guess it shouldn,t DEBUG> BEFORE (Date) testDate : Sat Feb 15 08:00:00 BRST 2014 DEBUG> BEFORE (String) strTeste : 2014-02-15 08:00:00 BRST DEBUG> AFTER (Date) testDate : Sun Feb 16 07:00:00 BRT 2014 DEBUG> AFTER (String) strTeste : 2014-02-16 07:00:00 BRT – Giovanni Dec 04 '13 at 23:23
  • BRST means Brazil Daylight Savings Time, I just read my windows 7 settings and is said : "Summer time is configured to end 2014/02/16"! So I supposed that explain all. :) Sorry can´t vote :( my rep is below 15. – Giovanni Dec 04 '13 at 23:37
  • You can't vote yet, but you can accept an answer: http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work Thanks, glad we got to the bottom of this. – Tom McClure Dec 05 '13 at 00:13
0

Avoid legacy date-time classes

You are using troublesome old date-time classes that are now legacy, supplanted by the java.time classes.

Using java.time

If you want to work with generic 24-hour days without any time zone or offset-from-UTC, use the LocalDateTime class. If you always want to start at 8 AM, specify a LocalTime.

LocalDate ld = LocalDate.of( 2014 , Month.FEBRUARY , 15 ) ;
LocalTime lt = LocalTime.of( 8 , 0 ) ; // Specify hour in 24-hour clock, 0-23.
LocalDateTime ldt = LocalDateTime.of( ld , lt );

Represent your 24 hour span as a Duration.

Duration d = Duration.ofHours( 24 );
LocalDateTime ldtLater = ldt.plus( d );

If you want to work with specific moments on the timeline as seen through the lens of a region’s particular wall-clock time, then specify a ZoneId to get a ZonedDateTime.

ZoneId z = ZoneId.of( "America/Sao_Paulo" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
ZonedDateTime zdtLater = zdt.plus( d );

Note that adding 24 hours to a ZonedDateTime is not the same thing as adding a day. As you have learned the hard way, anomalies such as Daylight Saving Time (DST) means a day may be 23, 24, or 25 hours long, or even other lengths. So if you want to add a day and let java.time apply its logic to arrive at an appropriate time-of-day while taking into consideration anomalies such as DST, add days rather than hours.

ZonedDateTime zdtLater = zdt.plusDays( 1 );  

Or add a Period of one whole day rather than a Duration of 24 hours.

Period p = Period.ofDays( 1 );
ZonedDateTime zdtLater = zdt.plus( p );

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?

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.

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154