Anonymous | Login | Signup for a new account | 11-25-2024 00:06 PST |
Main | My View | View Issues | Change Log | Docs |
Viewing Issue Simple Details [ Jump to Notes ] | [ View Advanced ] [ Issue History ] [ Print ] | |||||||||||
ID | Category | Severity | Reproducibility | Date Submitted | Last Update | |||||||
0006012 | [Quercus] | major | always | 06-16-16 11:11 | 06-16-16 11:11 | |||||||
Reporter | matthiasblaesing | View Status | public | |||||||||
Assigned To | ||||||||||||
Priority | normal | Resolution | open | |||||||||
Status | new | Product Version | 4.0.36 | |||||||||
Summary | 0006012: [PATCH] Adjust mktime implementation to align with PHP implementation | |||||||||||
Description |
The mktime implementation tries to implement the logic as defined by the reference implementation. This fails for some negative values + spills. The idea of my change: Use a GregorianCalendar from the JDK, in the lentient mode it mimiks mktime better than the current implementation. ------------------ Test.php ------------------ <?php // Test correct mktime behaviour, it is asumed, that strftime and mktime both // work in "default" timezone print "========== Test Spill ========\n"; $tests = array( // Testdata: hours, minutes, seconds, month, day, year array(22, 21, 1, 4, 21, 2016, "2016-04-21 22:21:01"), // Simple case array(30, 0, 0, 4, 21, 2016, "2016-04-22 06:00:00"), // Rollover hour array(-1, 0, 0, 4, 21, 2016, "2016-04-20 23:00:00"), // Negative hour array(-25, 0, 0, 4, 21, 2016, "2016-04-19 23:00:00"), // Negative hour > 24 array(2, 67, 0, 4, 21, 2016, "2016-04-21 03:07:00"), // Rollover minute array(2, -5, 0, 4, 21, 2016, "2016-04-21 01:55:00"), // Negative minute array(2, -125, 0, 4, 21, 2016, "2016-04-20 23:55:00"), // Negative minute > 120 array(2, 0, 65, 4, 21, 2016, "2016-04-21 02:01:05"), // Rollover second array(2, 1, -30, 4, 21, 2016, "2016-04-21 02:00:30"), // Negative minute array(2, 1, -150, 4, 21, 2016, "2016-04-21 01:58:30"), // Negative minute > 120 array(2, 0, 0, 4, 31, 2016, "2016-05-01 02:00:00"), // Rollover day array(2, 0, 0, 4, -1, 2016, "2016-03-30 02:00:00"), // Negative day array(2, 0, 0, 4, -56, 2016, "2016-02-04 02:00:00"), // Negative day > 30 array(2, 0, 0, 13, 4, 2016, "2017-01-04 02:00:00"), // Rollover month array(2, 0, 0, -1, 4, 2016, "2015-11-04 02:00:00"), // Negative month array(2, 0, 0, -13, 4, 2016, "2014-11-04 02:00:00"), // Negative month > 12 ); foreach($tests as $test) { $mktime = mktime($test[0], $test[1], $test[2], $test[3], $test[4], $test[5]); $timeString = strftime("%Y-%m-%d %H:%M:%S", $mktime); printf("mktime(%d, %d, %d, %d, %d, %d)\t=> Should be: %s -- IS: %s (%s)\n", $test[0], $test[1], $test[2], $test[3], $test[4], $test[5], $test[6], $timeString, $timeString == $test[6] ? "OK" : "BROKEN" ); } // gmmktime needs to be tested seperatedly, as strftime can't be used print "\n========= Test gmmktime ========\n"; // This timestamp is the unixtimestamp for 2016-06-16T17:49:14+00:00: 1466099354 print (gmmktime(17, 49, 14, 6, 16, 2016) == 1466099354 ? 'WORKS' : 'FAILS'); print "\n\n"; ------------------ Output for php 7 ------------------ ========== Test Spill ======== mktime(22, 21, 1, 4, 21, 2016) => Should be: 2016-04-21 22:21:01 -- IS: 2016-04-21 22:21:01 (OK) mktime(30, 0, 0, 4, 21, 2016) => Should be: 2016-04-22 06:00:00 -- IS: 2016-04-22 06:00:00 (OK) mktime(-1, 0, 0, 4, 21, 2016) => Should be: 2016-04-20 23:00:00 -- IS: 2016-04-20 23:00:00 (OK) mktime(-25, 0, 0, 4, 21, 2016) => Should be: 2016-04-19 23:00:00 -- IS: 2016-04-19 23:00:00 (OK) mktime(2, 67, 0, 4, 21, 2016) => Should be: 2016-04-21 03:07:00 -- IS: 2016-04-21 03:07:00 (OK) mktime(2, -5, 0, 4, 21, 2016) => Should be: 2016-04-21 01:55:00 -- IS: 2016-04-21 01:55:00 (OK) mktime(2, -125, 0, 4, 21, 2016) => Should be: 2016-04-20 23:55:00 -- IS: 2016-04-20 23:55:00 (OK) mktime(2, 0, 65, 4, 21, 2016) => Should be: 2016-04-21 02:01:05 -- IS: 2016-04-21 02:01:05 (OK) mktime(2, 1, -30, 4, 21, 2016) => Should be: 2016-04-21 02:00:30 -- IS: 2016-04-21 02:00:30 (OK) mktime(2, 1, -150, 4, 21, 2016) => Should be: 2016-04-21 01:58:30 -- IS: 2016-04-21 01:58:30 (OK) mktime(2, 0, 0, 4, 31, 2016) => Should be: 2016-05-01 02:00:00 -- IS: 2016-05-01 02:00:00 (OK) mktime(2, 0, 0, 4, -1, 2016) => Should be: 2016-03-30 02:00:00 -- IS: 2016-03-30 02:00:00 (OK) mktime(2, 0, 0, 4, -56, 2016) => Should be: 2016-02-04 02:00:00 -- IS: 2016-02-04 02:00:00 (OK) mktime(2, 0, 0, 13, 4, 2016) => Should be: 2017-01-04 02:00:00 -- IS: 2017-01-04 02:00:00 (OK) mktime(2, 0, 0, -1, 4, 2016) => Should be: 2015-11-04 02:00:00 -- IS: 2015-11-04 02:00:00 (OK) mktime(2, 0, 0, -13, 4, 2016) => Should be: 2014-11-04 02:00:00 -- IS: 2014-11-04 02:00:00 (OK) ========= Test gmmktime ======== WORKS ------------------ Output for quercus with patch ------------------ ========== Test Spill ======== mktime(22, 21, 1, 4, 21, 2016) => Should be: 2016-04-21 22:21:01 -- IS: 2016-04-21 22:21:01 (OK) mktime(30, 0, 0, 4, 21, 2016) => Should be: 2016-04-22 06:00:00 -- IS: 2016-04-22 06:00:00 (OK) mktime(-1, 0, 0, 4, 21, 2016) => Should be: 2016-04-20 23:00:00 -- IS: 2016-04-20 23:00:00 (OK) mktime(-25, 0, 0, 4, 21, 2016) => Should be: 2016-04-19 23:00:00 -- IS: 2016-04-19 23:00:00 (OK) mktime(2, 67, 0, 4, 21, 2016) => Should be: 2016-04-21 03:07:00 -- IS: 2016-04-21 03:07:00 (OK) mktime(2, -5, 0, 4, 21, 2016) => Should be: 2016-04-21 01:55:00 -- IS: 2016-04-21 01:55:00 (OK) mktime(2, -125, 0, 4, 21, 2016) => Should be: 2016-04-20 23:55:00 -- IS: 2016-04-20 23:55:00 (OK) mktime(2, 0, 65, 4, 21, 2016) => Should be: 2016-04-21 02:01:05 -- IS: 2016-04-21 02:01:05 (OK) mktime(2, 1, -30, 4, 21, 2016) => Should be: 2016-04-21 02:00:30 -- IS: 2016-04-21 02:00:30 (OK) mktime(2, 1, -150, 4, 21, 2016) => Should be: 2016-04-21 01:58:30 -- IS: 2016-04-21 01:58:30 (OK) mktime(2, 0, 0, 4, 31, 2016) => Should be: 2016-05-01 02:00:00 -- IS: 2016-05-01 02:00:00 (OK) mktime(2, 0, 0, 4, -1, 2016) => Should be: 2016-03-30 02:00:00 -- IS: 2016-03-30 02:00:00 (OK) mktime(2, 0, 0, 4, -56, 2016) => Should be: 2016-02-04 02:00:00 -- IS: 2016-02-04 02:00:00 (OK) mktime(2, 0, 0, 13, 4, 2016) => Should be: 2017-01-04 02:00:00 -- IS: 2017-01-04 02:00:00 (OK) mktime(2, 0, 0, -1, 4, 2016) => Should be: 2015-11-04 02:00:00 -- IS: 2015-11-04 02:00:00 (OK) mktime(2, 0, 0, -13, 4, 2016) => Should be: 2014-11-04 02:00:00 -- IS: 2014-11-04 02:00:00 (OK) ========= Test gmmktime ======== WORKS ------------------ Output for quercus without patch ------------------ ========== Test Spill ======== mktime(22, 21, 1, 4, 21, 2016) => Should be: 2016-04-21 22:21:01 -- IS: 2016-04-21 22:21:01 (OK) mktime(30, 0, 0, 4, 21, 2016) => Should be: 2016-04-22 06:00:00 -- IS: 2016-04-21 06:00:00 (BROKEN) mktime(-1, 0, 0, 4, 21, 2016) => Should be: 2016-04-20 23:00:00 -- IS: 2016-04-20 23:00:00 (OK) mktime(-25, 0, 0, 4, 21, 2016) => Should be: 2016-04-19 23:00:00 -- IS: 2016-04-19 23:00:00 (OK) mktime(2, 67, 0, 4, 21, 2016) => Should be: 2016-04-21 03:07:00 -- IS: 2016-04-21 02:07:00 (BROKEN) mktime(2, -5, 0, 4, 21, 2016) => Should be: 2016-04-21 01:55:00 -- IS: 2016-04-21 01:55:00 (OK) mktime(2, -125, 0, 4, 21, 2016) => Should be: 2016-04-20 23:55:00 -- IS: 2016-04-20 23:55:00 (OK) mktime(2, 0, 65, 4, 21, 2016) => Should be: 2016-04-21 02:01:05 -- IS: 2016-04-21 02:00:05 (BROKEN) mktime(2, 1, -30, 4, 21, 2016) => Should be: 2016-04-21 02:00:30 -- IS: 2016-04-21 02:00:30 (OK) mktime(2, 1, -150, 4, 21, 2016) => Should be: 2016-04-21 01:58:30 -- IS: 2016-04-21 01:58:30 (OK) mktime(2, 0, 0, 4, 31, 2016) => Should be: 2016-05-01 02:00:00 -- IS: 2016-04-01 02:00:00 (BROKEN) mktime(2, 0, 0, 4, -1, 2016) => Should be: 2016-03-30 02:00:00 -- IS: 2016-03-29 02:00:00 (BROKEN) mktime(2, 0, 0, 4, -56, 2016) => Should be: 2016-02-04 02:00:00 -- IS: 2016-02-04 02:00:00 (OK) mktime(2, 0, 0, 13, 4, 2016) => Should be: 2017-01-04 02:00:00 -- IS: 2016-06-04 02:00:00 (BROKEN) mktime(2, 0, 0, -1, 4, 2016) => Should be: 2015-11-04 02:00:00 -- IS: 2015-11-04 02:00:00 (OK) mktime(2, 0, 0, -13, 4, 2016) => Should be: 2014-11-04 02:00:00 -- IS: 2014-11-04 02:00:00 (OK) ========= Test gmmktime ======== WORKS ------------------ Patch ------------------ diff --git a/modules/quercus/src/com/caucho/quercus/lib/date/DateModule.java b/modules/quercus/src/com/caucho/quercus/lib/date/DateModule.java index 21a7ccf..1a78bdf 100644 --- a/modules/quercus/src/com/caucho/quercus/lib/date/DateModule.java +++ b/modules/quercus/src/com/caucho/quercus/lib/date/DateModule.java @@ -38,6 +38,8 @@ import com.caucho.quercus.module.AbstractQuercusModule; import com.caucho.util.CharBuffer; import com.caucho.util.L10N; import com.caucho.util.QDate; +import java.util.Calendar; +import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Map; @@ -332,18 +334,11 @@ public class DateModule extends AbstractQuercusModule { @Optional() Value dayV, @Optional() Value yearV) { - QDate date = env.getGmtDate(); - long now = env.getCurrentTime(); - - date.setLocalTime(now); - - long gmtNow = date.getGMTTime(); + GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("GMT")); - date.setGMTTime(gmtNow); + setMktime(gc, hourV, minuteV, secondV, monthV, dayV, yearV); - setMktime(date, hourV, minuteV, secondV, monthV, dayV, yearV); - - return date.getGMTTime() / 1000L; + return gc.getTimeInMillis() / 1000L; } /** @@ -907,17 +902,14 @@ public class DateModule extends AbstractQuercusModule { if (isDST != -1) env.deprecatedArgument("isDST"); - long now = env.getCurrentTime(); - - QDate date = env.getDate(); - date.setGMTTime(now); + GregorianCalendar gc = new GregorianCalendar(); - setMktime(date, hourV, minuteV, secondV, monthV, dayV, yearV); + setMktime(gc, hourV, minuteV, secondV, monthV, dayV, yearV); - return date.getGMTTime() / 1000L; + return gc.getTimeInMillis() / 1000L; } - private static void setMktime(QDate date, + private static void setMktime(Calendar date, Value hourV, Value minuteV, Value secondV, @@ -925,70 +917,8 @@ public class DateModule extends AbstractQuercusModule { Value dayV, Value yearV) { - int yearsToAdd = 0; - int monthsToAdd = 0; - int daysToAdd = 0; - - int hoursToAdd = 0; - int minsToAdd = 0; - - if (! secondV.isDefault()) { - int second = secondV.toInt(); - - if (second < 0) { - minsToAdd = second / 60 - (second % 60 != 0 ? 1 : 0); - second = second % 60 + 60; - } - - date.setSecond(second); - } - - if (! minuteV.isDefault()) { - int minute = minuteV.toInt() + minsToAdd; - - if (minute < 0) { - hoursToAdd = minute / 60 - (minute % 60 != 0 ? 1 : 0); - minute = minute % 60 + 60; - } - - date.setMinute(minute); - } - - if (! hourV.isDefault()) { - int hour = hourV.toInt() + hoursToAdd; - - if (hour < 0) { - daysToAdd = hour / 24 - (hour % 24 != 0 ? 1 : 0); - hour = hour % 24 + 24; - } - - date.setHour(hour); - } - - if (! dayV.isDefault()) { - int day = dayV.toInt() + daysToAdd; - - if (day <= 0) { - monthsToAdd = day / 30 - 1; - day = day % 30 + 30; - } - - date.setDayOfMonth(day); - } - - if (! monthV.isDefault()) { - int month = monthV.toInt() + monthsToAdd; - - if (month <= 0) { - yearsToAdd = month / 12 - 1; - month = month % 12 + 12; - } - - date.setMonth(month - 1); - } - if (! yearV.isDefault()) { - int year = yearV.toInt() + yearsToAdd; + int year = yearV.toInt(); if (year >= 1000) { } @@ -1002,8 +932,29 @@ public class DateModule extends AbstractQuercusModule { year = 1969; } - date.setYear(year); + date.set(Calendar.YEAR, year); + } + + if (! monthV.isDefault()) { + date.set(Calendar.MONTH, monthV.toInt() - 1); + } + + if (! dayV.isDefault()) { + date.set(Calendar.DAY_OF_MONTH, dayV.toInt()); + } + + if (! hourV.isDefault()) { + date.set(Calendar.HOUR_OF_DAY, hourV.toInt()); } + + if (! minuteV.isDefault()) { + date.set(Calendar.MINUTE, minuteV.toInt()); + } + + if (! secondV.isDefault()) { + date.set(Calendar.SECOND, secondV.toInt()); + } + } /** |
|||||||||||
Additional Information | ||||||||||||
Attached Files | ||||||||||||
|
There are no notes attached to this issue. |
Mantis 1.0.0rc3[^]
Copyright © 2000 - 2005 Mantis Group
26 total queries executed. 24 unique queries executed. |