From: richard dot quadling at bandvulc dot co dot uk
Operating system: All
PHP version: 5.0.4
PHP Bug Type: Feature/Change Request
Bug description: Support ISO 8601 Year number for Week number
Description:
------------
This could also be a fix for a "Will Not Fix" bug #22711.
On Windows, the strftime() function does not support %V, %G or %g.
The date() function supports 'W' which deals with %V (if you get what I
mean), but when the week number is 52 or 53 and you are looking at a
January date, getting the correct year also would be useful.
I've included below a CVS diff datetime.c.
I don't know who to send it to.
date('V') emulates strftime('%G');
date('v') emulates strftime('%g');
I've also rewritten the date('W') code to combine with V and v.
Index: datetime.c
===================================================================
RCS file: /repository/php-src/ext/standard/datetime.c,v
retrieving revision 1.129
diff -u -r1.129 datetime.c
--- datetime.c 19 Jun 2005 22:15:26 -0000 1.129
+++ datetime.c 23 Jun 2005 08:00:48 -0000
@@ -288,7 +288,7 @@
pval **format, **timestamp;
time_t the_time;
struct tm *ta, tmbuf;
- int i, size = 0, length, h, beat, fd, wd, yd, wk;
+ int i, size = 0, length, h, beat, fd, wd, yd, wk, yr;
char tmp_buff[32];
#if !HAVE_TM_GMTOFF
long tzone;
@@ -382,6 +382,7 @@
size += 5;
break;
case 'Y': /* year, numeric, 4 digits */
+ case 'V': /* ISO-8601 year number of year, numeric, 4 digits */
size += 4;
break;
case 'M': /* month, textual, 3 letters */
@@ -406,6 +407,7 @@
case 'S': /* standard english suffix for the day of the month (e.g.
3rd, 2nd, etc) */
case 't': /* days in current month */
case 'W': /* ISO-8601 week number of year, weeks starting on Monday
*/
+ case 'v': /* ISO-8601 year number of year, numeric, 2 digits */
size += 2;
break;
case '\\':
@@ -641,27 +643,67 @@
strcat(Z_STRVAL_P(return_value), tmp_buff);
break;
case 'W': /* ISO-8601 week number of year, weeks starting on Monday
*/
- wd = ta->tm_wday == 0 ? 6 : ta->tm_wday - 1; /* weekday */
- yd = ta->tm_yday + 1; /* days since January 1st */
-
- fd = (7 + wd - yd % 7+ 1) % 7; /* weekday (1st January) */
-
- /* week is a last year week (52 or 53) */
- if ((yd <= 7 - fd) && fd > 3){
- wk = (fd == 4 || (fd == 5 && isleap((ta->tm_year + YEAR_BASE - 1))))
? 53 : 52;
- }
- /* week is a next year week (1) */
- else if (isleap((ta->tm_year+YEAR_BASE)) + 365 - yd < 3 - wd){
- wk = 1;
+ case 'V': /* ISO-8601 year number of year, numeric, 4 digits */
+ case 'v': /* ISO-8601 year number of year, numeric, 2 digits */
+ yr = ta->tm_year + YEAR_BASE;
+ yd = ta->tm_yday;
+ wd = ta->tm_wday;
+ while(1) {
+ int len, bot, top;
+
+ len = isleap(yr) ? 366 : 365;
+ bot = ((yd + 11 - wd) % 7) - 3;
+ top = bot - (len % 7);
+ if (top < -3) {
+ top += 7;
+ }
+ top += len;
+ if (yd >= top) {
+ ++yr;
+ w = 1;
+ break;
+ }
+ if (yd >= bot) {
+ w = 1 + ((yd - bot) / 7);
+ break;
+ }
+ --year;
+ yd += isleap(yr) ? 366 : 365;
}
- /* normal week */
- else {
- wk = (yd + 6 - wd + fd) / 7 - (fd > 3);
+ switch (Z_STRVAL_PP(format)[i]) {
+ case 'W': /* ISO-8601 week number of year, weeks starting on Monday
*/
+ sprintf(tmp_buff, "%d", wk); /* SAFE */
+ break;
+ case 'V': /* ISO-8601 year number of year, numeric, 4 digits */
+ sprintf(tmp_buff, "%d", yr); /* SAFE */
+ break;
+ case 'v': /* ISO-8601 year number of year, numeric, 2 digits */
+ sprintf(tmp_buff, "%02d", yr % 100); /* SAFE */
+ break;
}
-
- sprintf(tmp_buff, "%d", wk); /* SAFE */
strcat(Z_STRVAL_P(return_value), tmp_buff);
break;
+// wd = ta->tm_wday == 0 ? 6 : ta->tm_wday - 1; /* weekday */
+// yd = ta->tm_yday + 1; /* days since January 1st */
+
+// fd = (7 + wd - yd % 7+ 1) % 7; /* weekday (1st January) */
+
+// /* week is a last year week (52 or 53) */
+// if ((yd <= 7 - fd) && fd > 3){
+// wk = (fd == 4 || (fd == 5 && isleap((ta->tm_year + YEAR_BASE -
1)))) ? 53 : 52;
+// }
+// /* week is a next year week (1) */
+// else if (isleap((ta->tm_year+YEAR_BASE)) + 365 - yd < 3 - wd){
+// wk = 1;
+// }
+// /* normal week */
+// else {
+// wk = (yd + 6 - wd + fd) / 7 - (fd > 3);
+// }
+
+// sprintf(tmp_buff, "%d", wk); /* SAFE */
+// strcat(Z_STRVAL_P(return_value), tmp_buff);
+// break;
default:
length = strlen(Z_STRVAL_P(return_value));
@@ -773,22 +815,62 @@
case 'I':
return ta->tm_isdst;
case 'W': /* ISO-8601 week number of year, weeks starting on Monday
*/
- wd = (ta->tm_wday == 0) ? 6 : ta->tm_wday - 1; /* weekday */
- yd = ta->tm_yday + 1; /* days since January 1st */
- fd = (7 + wd - yd % 7+ 1) % 7; /* weekday (1st January) */
- if ((yd <= 7 - fd) && fd > 3) { /* week is a last year week (52 or
53) */
- wk = (fd == 4 || (fd == 5 && isleap((ta->tm_year + YEAR_BASE - 1))))
? 53 : 52;
- }
- /* week is a next year week (1) */
- else if (isleap((ta->tm_year + YEAR_BASE)) + 365 - yd < 3 - wd) {
- wk = 1;
+ case 'V': /* ISO-8601 year number of year, numeric, 4 digits */
+ case 'v': /* ISO-8601 year number of year, numeric, 2 digits */
+ yr = ta->tm_year + YEAR_BASE;
+ yd = ta->tm_yday;
+ wd = ta->tm_wday;
+ while(1) {
+ int len, bot, top;
+
+ len = isleap(yr) ? 366 : 365;
+ bot = ((yd + 11 - wd) % 7) - 3;
+ top = bot - (len % 7);
+ if (top < -3) {
+ top += 7;
+ }
+ top += len;
+ if (yd >= top) {
+ ++yr;
+ w = 1;
+ break;
+ }
+ if (yd >= bot) {
+ w = 1 + ((yd - bot) / 7);
+ break;
+ }
+ --year;
+ yd += isleap(yr) ? 366 : 365;
}
- /* normal week */
- else {
- wk = (yd + 6 - wd + fd) / 7 - (fd > 3);
+ switch (format) {
+ case 'W': /* ISO-8601 week number of year, weeks starting on Monday
*/
+ return wk;
+ break;
+ case 'V': /* ISO-8601 year number of year, numeric, 4 digits */
+ return yr;
+ break;
+ case 'v': /* ISO-8601 year number of year, numeric, 2 digits */
+ yr = yr % 100
+ return yr;
+ break;
}
- return wk;
break;
+// wd = (ta->tm_wday == 0) ? 6 : ta->tm_wday - 1; /* weekday */
+// yd = ta->tm_yday + 1; /* days since January 1st */
+// fd = (7 + wd - yd % 7+ 1) % 7; /* weekday (1st January) */
+// if ((yd <= 7 - fd) && fd > 3) { /* week is a last year week (52 or
53) */
+// wk = (fd == 4 || (fd == 5 && isleap((ta->tm_year + YEAR_BASE -
1)))) ? 53 : 52;
+// }
+// /* week is a next year week (1) */
+// else if (isleap((ta->tm_year + YEAR_BASE)) + 365 - yd < 3 - wd) {
+// wk = 1;
+// }
+// /* normal week */
+// else {
+// wk = (yd + 6 - wd + fd) / 7 - (fd > 3);
+// }
+// return wk;
+// break;
default:
return 0;
}
Regards,
Richard Quadling.
--
Edit bug report at http://bugs.php.net/?id=33445&edit=1
--
Try a CVS snapshot (php4): http://bugs.php.net/fix.php?id=33445&r=trysnapshot4
Try a CVS snapshot (php5.0): http://bugs.php.net/fix.php?id=33445&r=trysnapshot50
Try a CVS snapshot (php5.1): http://bugs.php.net/fix.php?id=33445&r=trysnapshot51
Fixed in CVS: http://bugs.php.net/fix.php?id=33445&r=fixedcvs
Fixed in release: http://bugs.php.net/fix.php?id=33445&r=alreadyfixed
Need backtrace: http://bugs.php.net/fix.php?id=33445&r=needtrace
Need Reproduce Script: http://bugs.php.net/fix.php?id=33445&r=needscript
Try newer version: http://bugs.php.net/fix.php?id=33445&r=oldversion
Not developer issue: http://bugs.php.net/fix.php?id=33445&r=support
Expected behavior: http://bugs.php.net/fix.php?id=33445&r=notwrong
Not enough info: http://bugs.php.net/fix.php?id=33445&r=notenoughinfo
Submitted twice: http://bugs.php.net/fix.php?id=33445&r=submittedtwice
register_globals: http://bugs.php.net/fix.php?id=33445&r=globals
PHP 3 support discontinued: http://bugs.php.net/fix.php?id=33445&r=php3
Daylight Savings: http://bugs.php.net/fix.php?id=33445&r=dst
IIS Stability: http://bugs.php.net/fix.php?id=33445&r=isapi
Install GNU Sed: http://bugs.php.net/fix.php?id=33445&r=gnused
Floating point limitations: http://bugs.php.net/fix.php?id=33445&r=float
No Zend Extensions: http://bugs.php.net/fix.php?id=33445&r=nozend
MySQL Configuration Error: http://bugs.php.net/fix.php?id=33445&r=mysqlcfg