php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #33445 strftime() arguments are system dependent
Submitted: 2005-06-23 10:17 UTC Modified: 2017-01-11 06:54 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:0 of 1 (0.0%)
From: richard dot quadling at bandvulc dot co dot uk Assigned:
Status: Wont fix Package: Date/time related
PHP Version: 5.0.4 OS: *
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: richard dot quadling at bandvulc dot co dot uk
New email:
PHP Version: OS:

 

 [2005-06-23 10:17 UTC] richard dot quadling at bandvulc dot co dot uk
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.



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-06-23 10:44 UTC] richard dot quadling at bandvulc dot co dot uk
Maybe a better solution would be to make the strftime and date functions the same and to consolidate the code to remove the dependency on platform specific libraries (e.g. the Windows strftime function does not support V,G or g).

Alternatively, amend the documentation to indicate which formats are supported by which platform.

It does seem that both of these functions do the same job and could be consilidated though.

Richard.
 [2005-06-23 13:32 UTC] derick@php.net
This will be re-implemented very soon, so stay tuned!
 [2005-08-11 20:15 UTC] nlopess@php.net
Already implemented in PHP 5.1 as date('o').
 [2005-08-11 20:18 UTC] derick@php.net
The fix up of strftime() is not done though - please keep it assigned.
 [2010-12-20 14:12 UTC] jani@php.net
-Summary: strftime's arguments are system dependent +Summary: strftime() arguments are system dependent -Package: Feature/Change Request +Package: Date/time related
 [2013-01-06 16:08 UTC] derick@php.net
-Status: Assigned +Status: Open -Assigned To: derick +Assigned To:
 [2017-01-11 06:54 UTC] heiglandreas@php.net
-Status: Open +Status: Wont fix
 [2017-01-11 06:54 UTC] heiglandreas@php.net
As this issue by now is more than 10 years old and targets an unsupported version of PHP I'm going to close it.

Should this still be an issue feel free to reopen it
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC