#33445 [NEW]: Support ISO 8601 Year number for Week number

From: Date: Thu, 23 Jun 2005 08:17:58 +0000
Subject: #33445 [NEW]: Support ISO 8601 Year number for Week number
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-80868@lists.php.net to get a copy of this message
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


Thread (7 messages)

« previous php.bugs (#80868) next »