Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 1.5.0a4

Bug #11313 DST time change not handled correctly
Submitted: 2007-06-13 11:31 UTC Modified: 2008-03-23 19:07 UTC
From: hubbitus Assigned: c01234
Status: Closed Package: Date (version 1.4.7)
PHP Version: 5.1.6 OS: ASPLinux(Fedora)
Roadmaps: (Not assigned)    
Subscription  


 [2007-06-13 11:31 UTC] hubbitus (Pavel Alexeev)
Description: ------------ In timezone 'Europe/Moscow', for example, in DST to EST changed on 2007-03-25 02:00:00 to set time on 2007-03-25 03:00:00. Thus, for example time 2007-03-25 02:30:04 is NOT correct for the given time zone. And this hour is not considered in operations of addition and subtraction of dates. It should seems to me such correction to be for time intervals of type of "hours", "minutes". But should not concern, "days", "months", there there should be already old logic. And I thought above correction, I think it is necessary to consider separately all the same a difference of dates in DST and EST, thus separately to consider an interval on which displacement is required. Well and for calculation of time of this translation of hours, it is necessary is similar iterative to touch days of March and October. http://en.wikipedia.org/wiki/European_Summer_Time Test script: --------------- <?php putenv('TZ=Europe/Moscow'); //include_once('debug.php'); require_once 'Date.php'; $date = new Date('2007-03-25 03:00:04'); $tmp = new Date($date); $PRINT_FORMAT = "%Y-%m-%d %H:%M:%S %Z%O"; //var_dump($date->tz, 'TimeZone'); printf("% 50s: %s\n", "Actual date", $date->format($PRINT_FORMAT)); $tmp->copy($date); $tmp->subtractSpan(new Date_Span('0:00:00:05')); printf("% 50s: %s\n", 'Subtracting 5 seconds', $tmp->format($PRINT_FORMAT)); $tmp->copy($date); $tmp->subtractSpan(new Date_Span('0:00:20:00')); printf("% 50s: %s\n", "Subtracting 20 minutes", $tmp->format($PRINT_FORMAT)); $tmp->copy($date); $tmp->subtractSpan(new Date_Span('0:02:30:00')); printf("% 50s: %s\n", "Subtracting 2 hours 30 minutes", $tmp->format($PRINT_FORMAT)); $tmp->copy($date); $tmp->subtractSpan(new Date_Span('0:10:00:00')); printf("% 50s: %s\n", "Subtracting 10 hours", $tmp->format($PRINT_FORMAT)); $tmp->copy($date); $tmp->subtractSpan(new Date_Span('3:00:00:00')); printf("% 50s: %s\n", "Subtracting 3 days", $tmp->format($PRINT_FORMAT)); ?> Expected result: ---------------- Actual date: 2007-03-25 03:00:04 MSD+04:00 Subtracting 5 seconds: 2007-03-25 01:59:59 MSD+04:00 Subtracting 20 minutes: 2007-03-25 01:40:04 MSD+04:00 Subtracting 2 hours 30 minutes: 2007-03-24 23:30:04 MSK+03:00 Subtracting 10 hours: 2007-03-24 17:00:04 MSK+03:00 Subtracting 3 days: 2007-03-22 03:00:04 MSK+03:00 Actual result: -------------- Actual date: 2007-03-25 03:00:04 MSD+04:00 Subtracting 5 seconds: 2007-03-25 02:59:59 MSD+04:00 Subtracting 20 minutes: 2007-03-25 02:40:04 MSD+04:00 Subtracting 2 hours 30 minutes: 2007-03-25 00:30:04 MSK+03:00 Subtracting 10 hours: 2007-03-24 17:00:04 MSK+03:00 Subtracting 3 days: 2007-03-22 03:00:04 MSK+03:00

Comments

 [2007-11-15 06:59 UTC] c01234 (Chuckie Chuck)
I agree mostly. This is what I think the function should return, and what is implemented now in CVS: Actual date: 2007-03-25 03:00:04 MSD+04:00 Subtracting 5 seconds: 2007-03-25 01:59:59 MSK+03:00 Subtracting 20 minutes: 2007-03-25 01:40:04 MSK+03:00 Subtracting 2 hours 30 minutes: 2007-03-24 23:30:04 MSK+03:00 Subtracting 10 hours: 2007-03-24 16:00:04 MSK+03:00 Subtracting 3 days: 2007-03-22 02:00:04 MSK+03:00 Only the first date should be in Moscow Summer time. When subtracting 10 hours, I think the returned time should be 16.00, not 17.00, or else only 9 hours have truly been subtracted. When subtracting 3 days I think the returned time should be 2.00, not 3.00. If you preserve the time across day addition, then when you do an addition involving days and hours together, your results will depend on which order you do the addition: the hours and then the days, or the days then the hours. I appreciate that I am using a different logic for the addition of hours, but unless you add using real hours you run into real problems. For example: 2007-03-25 03:00:04 minus 1 hour = What? We cannot return 02.00.04 because this time is invalid (for this time zone). The user should expect 01.00.04, or at least, this is the least unexpected solution. If the user does not want this kind of behaviour, he should not set the time zone to Europe/Moscow, and should use UTC instead.
 [2007-11-17 06:00 UTC] hubbitus (Pavel Alexeev)
> Only the first date should be in Moscow Summer time. Ok, ok. This is my mistake. Off course should be MSK. > When subtracting 10 hours, I think the returned time should be 16.00 >, not 17.00, or else only 9 hours have truly been subtracted. Why??? > when you do an addition involving days and hours together, > your results will depend on which order you do the addition: the > hours and then the days, or the days then the hours. I think, firstly days, then hours. Order by weight: year, month, day, hour, minutes, seconds. > 2007-03-25 03:00:04 minus 1 hour = What? We cannot return 02.00.04 > because this time is invalid (for this time zone). The user should > expect 01.00.04, or at least, this is the least unexpected solution. > If the user does not want this kind of behavior, he should not set > the time zone to Europe/Moscow, and should use UTC instead. Fully agreed.
 [2007-11-17 08:40 UTC] c01234 (Chuckie Chuck)
Thanks for your reply. I think that most users probably would expect the days to be added such that 2007-03-25 03:00:04 minus 1 day = 2007-03-24 03:00:04 i.e. actually subtracting 23 hours. And this is what I would also expect myself, and so I was initially going to re-implement the function with this behaviour. But what about: 2007-03-26 02:00:04 minus 1 day = What? 2007-03-25 02:00:04 is not a valid time. But as the other problem, if you have a span, for example, of 1 day and 1 hour then the result of 'subtractSpan()' depends on the order in which you add these components. 1 day then 1 hour: 2007-03-25 03:00:04 minus span = 2007-03-24 02:00:04 1 hour then 1 day: 2007-03-25 03:00:04 minus span = 2007-03-24 01:00:04 And if you add the same span back using 'addSpan()': 1 day then 1 hour: 2007-03-24 02:00:04 plus span = 2007-03-24 04:00:04, although the result is not clear - this assumes that 1 day is in fact 24 hours, because 2.00.04 is an invalid time. 1 hour then 1 day: 2007-03-24 01:00:04 plus span = 2007-03-25 03:00:04 This is not good, because then the user has to be aware of how the function is implemented, and also because it breaks the concept of a 'span' - the true length of the span is now dependent on whether you add it or subtract it, and in which part of the year you do so.
 [2007-11-17 08:50 UTC] c01234 (Chuckie Chuck)
I should also add that I have added (in CVS) 'addDays()' 'addMonths()' ... etc. which does have the functionality you have talked about. I agree that this functionality is definitely useful and should be available, but not that it should be implemented in 'addSpan()' - it has to be combined in a way that does not yield unexpected behaviour.
 [2007-11-19 19:56 UTC] hubbitus (Pavel Alexeev)
Tank you for dialog. >I think that most users probably would expect the days to be added > such that > 2007-03-25 03:00:04 minus 1 day = 2007-03-24 03:00:04 Yes, I agree But >This is not good, because then the user has to be aware of how the > function is implemented, and also because it breaks the concept of a > 'span' - the true length of the span is now dependent on whether you > add it or subtract it, and in which part of the year you do so. No, length of the span dependent on part of the year only, nor operation on it. But that same, and so there really - length of span, for example "1 month and 3 day" don't have fixed length in hour! It depend of month - 29, 30 or 31 days. Additionally this depend of factor leap-year or not, if month is February. So, I think there can not be "span of time" in general, it must be tied to a specific date. At least on one side. OR if span do not have concrete date, operations of converting it to other unit (such as Number of month to days or hours, or Number of days to hours etc...) is invalid, is not deterministic. Thus, as the month has a different length, to take into account European Summer Time, the length of day is not a constant - 24 hours, and there may be 23 and 25 hours. And this also requires a thorough treatment. P.S. Excuse me for my bad English.
 [2007-11-21 11:04 UTC] c01234 (Chuckie Chuck)
> But that same, and so there really - length of span, for > example "1 month and 3 day" don't have fixed length in hour! > It depend of month - 29, 30 or 31 days. Additionally this > depend of factor leap-year or not, if month is February. Thankfully we don't have to worry about the month-length problem because you can only specify a span in days, hours, minutes and seconds. > if span do not have concrete date, operations of > converting it to other unit (such as Number of month to > days or hours, or Number of days to hours etc...) is > invalid, is not deterministic. We have to bear in mind that these functions already do exist. Also bear in mind that if you specify a span of 25 hours, for example, the Date_Span class stores this as 1 day and 1 hour. So behaviour also exists which treats the day as being 24 hours. I think that it is perfectly reasonable to treat the day in the way you describe (i.e. 23/24/25 hours depending on the specific date), but I think that the decision is a matter of weighing the advantages and disadvantages against implementing the function in a way that always treats 1 day as 24 hours. Just bear in mind then that the current behaviour of the Date_Span class is quite a big disadvantage of treating the day as 23/24/25 hours, because you would then have to change this behaviour (which would be backwards incompatible), or leave it (which would be inconsistent and confusing). > So, I think there can not be "span of time" in general, it > must be tied to a specific date. I see no reason why the user cannot just call 'addDays(1)' and then 'addHours(1)' instead of creating a Date_Span and calling 'addSpan($object)'. Perhaps we should consider deprecating this function?
 [2007-12-14 16:38 UTC] hubbitus (Pavel Alexeev)
Ok, I understand you. May be for backwards compatibility current behavior can not be changed, which based on this limitations and simplifications (such as 24 hours in day, Date_Span without month, years etc...). And, off course this logic easy to implement, and very fast work. And if you have no objections, may be I can fork your class to implement more precision in dates?
 [2008-03-23 19:07 UTC] c01234 (Chuckie Chuck)
Thank you for your bug report. This issue has been fixed in the latest released version of the package, which you can download at http://pear.php.net/get/Date