Use PHP functions in JavaScript

JavaScript date

Format a local date/time

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
22
23
24
2526
27
28
29
3031
32
33
34
3536
37
38
39
4041
42
43
44
4546
47
48
49
5051
52
53
54
5556
57
58
59
6061
62
63
64
6566
67
68
69
7071
72
73
74
7576
77
78
79
8081
82
83
84
8586
87
88
89
9091
92
93
94
9596
97
98
99
100101
102
103
104
105106
107
108
109
110111
112
113
114
115116
117
118
119
120121
122
123
124
125126
127
128
129
130131
132
133
134
135136
137
138
139
140141
142
143
144
145146
147
148
149
150151
152
153
154
155156
157
158
159
160161
162
163
164
165166
167
168
169
170171
172
173
174
175176
177
178
179
180181
182
183
184
185186
187
188
189
190191
192
193
194
195196
197
198
199
200201
202
203
204
205206
207
208
209
210211
212
213
214
215216
217
218
219
220221
222
223
224
225226
227
228
229
230231
232
233
234
235236
237
238
239
240241
242
243
244
245246
247
248
249
250251
252
253
254
255256
257
258
259
260261
262
263
264
265266
function date (format, timestamp) {
    // Format a local date/time  
    // 
    // version: 1109.2015
    // discuss at: http://phpjs.org/functions/date    // +   original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
    // +      parts by: Peter-Paul Koch (http://www.quirksmode.org/js/beat.html)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: MeEtc (http://yass.meetcweb.com)
    // +   improved by: Brad Touesnard    // +   improved by: Tim Wiel
    // +   improved by: Bryan Elliott
    //
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: David Randall    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault    // +  derived from: gettimeofday
    // +      input by: majak
    // +   bugfixed by: majak
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Alex    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +   improved by: Thomas Beaucourt (http://www.webapp.fr)    // +   improved by: JT
    // +   improved by: Theriault
    // +   improved by: Rafał Kukawski (http://blog.kukawski.pl)
    // +   bugfixed by: omid (http://phpjs.org/functions/380:380#comment_137122)
    // +      input by: Martin    // +      input by: Alex Wilson
    // %        note 1: Uses global: php_js to store the default timezone
    // %        note 2: Although the function potentially allows timezone info (see notes), it currently does not set
    // %        note 2: per a timezone specified by date_default_timezone_set(). Implementers might use
    // %        note 2: this.php_js.currentTimezoneOffset and this.php_js.currentTimezoneDST set by that function    // %        note 2: in order to adjust the dates in this function (or our other date functions!) accordingly
    // *     example 1: date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400);
    // *     returns 1: '09:09:40 m is month'
    // *     example 2: date('F j, Y, g:i a', 1062462400);
    // *     returns 2: 'September 2, 2003, 2:26 am'    // *     example 3: date('Y W o', 1062462400);
    // *     returns 3: '2003 36 2003'
    // *     example 4: x = date('Y m d', (new Date()).getTime()/1000); 
    // *     example 4: (x+'').length == 10 // 2009 01 09
    // *     returns 4: true    // *     example 5: date('W', 1104534000);
    // *     returns 5: '53'
    // *     example 6: date('B t', 1104534000);
    // *     returns 6: '999 31'
    // *     example 7: date('W U', 1293750000.82); // 2010-12-31    // *     returns 7: '52 1293750000'
    // *     example 8: date('W', 1293836400); // 2011-01-01
    // *     returns 8: '52'
    // *     example 9: date('W Y-m-d', 1293974054); // 2011-01-02
    // *     returns 9: '52 2011-01-02'    var that = this,
        jsdate, f, formatChr = /\\?([a-z])/gi,
        formatChrCb,
        // Keep this here (works, but for code commented-out
        // below for file size reasons)        //, tal= [],
        _pad = function (n, c) {
            if ((n = n + '').length < c) {
                return new Array((++c) - n.length).join('0') + n;
            }            return n;
        },
        txt_words = ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    formatChrCb = function (t, s) {
        return f[t] ? f[t]() : s;    };
    f = {
        // Day
        d: function () { // Day of month w/leading 0; 01..31
            return _pad(f.j(), 2);        },
        D: function () { // Shorthand day name; Mon...Sun
            return f.l().slice(0, 3);
        },
        j: function () { // Day of month; 1..31            return jsdate.getDate();
        },
        l: function () { // Full day name; Monday...Sunday
            return txt_words[f.w()] + 'day';
        },        N: function () { // ISO-8601 day of week; 1[Mon]..7[Sun]
            return f.w() || 7;
        },
        S: function () { // Ordinal suffix for day of month; st, nd, rd, th
            var j = f.j();            return j > 4 && j < 21 ? 'th' : {1: 'st', 2: 'nd', 3: 'rd'}[j % 10] || 'th';
        },
        w: function () { // Day of week; 0[Sun]..6[Sat]
            return jsdate.getDay();
        },        z: function () { // Day of year; 0..365
            var a = new Date(f.Y(), f.n() - 1, f.j()),
                b = new Date(f.Y(), 0, 1);
            return Math.round((a - b) / 864e5) + 1;
        }, 
        // Week
        W: function () { // ISO-8601 week number
            var a = new Date(f.Y(), f.n() - 1, f.j() - f.N() + 3),
                b = new Date(a.getFullYear(), 0, 4);            return _pad(1 + Math.round((a - b) / 864e5 / 7), 2);
        },
 
        // Month
        F: function () { // Full month name; January...December            return txt_words[6 + f.n()];
        },
        m: function () { // Month w/leading 0; 01...12
            return _pad(f.n(), 2);
        },        M: function () { // Shorthand month name; Jan...Dec
            return f.F().slice(0, 3);
        },
        n: function () { // Month; 1...12
            return jsdate.getMonth() + 1;        },
        t: function () { // Days in month; 28...31
            return (new Date(f.Y(), f.n(), 0)).getDate();
        },
         // Year
        L: function () { // Is leap year?; 0 or 1
            return new Date(f.Y(), 1, 29).getMonth() === 1 | 0;
        },
        o: function () { // ISO-8601 year            var n = f.n(),
                W = f.W(),
                Y = f.Y();
            return Y + (n === 12 && W < 9 ? -1 : n === 1 && W > 9);
        },        Y: function () { // Full year; e.g. 1980...2010
            return jsdate.getFullYear();
        },
        y: function () { // Last two digits of year; 00...99
            return (f.Y() + "").slice(-2);        },
 
        // Time
        a: function () { // am or pm
            return jsdate.getHours() > 11 ? "pm" : "am";        },
        A: function () { // AM or PM
            return f.a().toUpperCase();
        },
        B: function () { // Swatch Internet time; 000..999            var H = jsdate.getUTCHours() * 36e2,
                // Hours
                i = jsdate.getUTCMinutes() * 60,
                // Minutes
                s = jsdate.getUTCSeconds(); // Seconds            return _pad(Math.floor((H + i + s + 36e2) / 86.4) % 1e3, 3);
        },
        g: function () { // 12-Hours; 1..12
            return f.G() % 12 || 12;
        },        G: function () { // 24-Hours; 0..23
            return jsdate.getHours();
        },
        h: function () { // 12-Hours w/leading 0; 01..12
            return _pad(f.g(), 2);        },
        H: function () { // 24-Hours w/leading 0; 00..23
            return _pad(f.G(), 2);
        },
        i: function () { // Minutes w/leading 0; 00..59            return _pad(jsdate.getMinutes(), 2);
        },
        s: function () { // Seconds w/leading 0; 00..59
            return _pad(jsdate.getSeconds(), 2);
        },        u: function () { // Microseconds; 000000-999000
            return _pad(jsdate.getMilliseconds() * 1000, 6);
        },
 
        // Timezone        e: function () { // Timezone identifier; e.g. Atlantic/Azores, ...
            // The following works, but requires inclusion of the very large
            // timezone_abbreviations_list() function.
/*              return this.date_default_timezone_get();
*/            throw 'Not supported (see source code of date() for timezone on how to add support)';
        },
        I: function () { // DST observed?; 0 or 1
            // Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC.
            // If they are not equal, then DST is observed.            var a = new Date(f.Y(), 0),
                // Jan 1
                c = Date.UTC(f.Y(), 0),
                // Jan 1 UTC
                b = new Date(f.Y(), 6),                // Jul 1
                d = Date.UTC(f.Y(), 6); // Jul 1 UTC
            return 0 + ((a - c) !== (b - d));
        },
        O: function () { // Difference to GMT in hour format; e.g. +0200            var tzo = jsdate.getTimezoneOffset(),
                a = Math.abs(tzo);
            return (tzo > 0 ? "-" : "+") + _pad(Math.floor(a / 60) * 100 + a % 60, 4);
        },
        P: function () { // Difference to GMT w/colon; e.g. +02:00            var O = f.O();
            return (O.substr(0, 3) + ":" + O.substr(3, 2));
        },
        T: function () { // Timezone abbreviation; e.g. EST, MDT, ...
            // The following works, but requires inclusion of the very            // large timezone_abbreviations_list() function.
/*              var abbr = '', i = 0, os = 0, default = 0;
            if (!tal.length) {
                tal = that.timezone_abbreviations_list();
            }            if (that.php_js && that.php_js.default_timezone) {
                default = that.php_js.default_timezone;
                for (abbr in tal) {
                    for (i=0; i < tal[abbr].length; i++) {
                        if (tal[abbr][i].timezone_id === default) {                            return abbr.toUpperCase();
                        }
                    }
                }
            }            for (abbr in tal) {
                for (i = 0; i < tal[abbr].length; i++) {
                    os = -jsdate.getTimezoneOffset() * 60;
                    if (tal[abbr][i].offset === os) {
                        return abbr.toUpperCase();                    }
                }
            }
*/
            return 'UTC';        },
        Z: function () { // Timezone offset in seconds (-43200...50400)
            return -jsdate.getTimezoneOffset() * 60;
        },
         // Full Date/Time
        c: function () { // ISO-8601 date.
            return 'Y-m-d\\Th:i:sP'.replace(formatChr, formatChrCb);
        },
        r: function () { // RFC 2822            return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb);
        },
        U: function () { // Seconds since UNIX epoch
            return jsdate.getTime() / 1000 | 0;
        }    };
    this.date = function (format, timestamp) {
        that = this;
        jsdate = ((typeof timestamp === 'undefined') ? new Date() : // Not provided
        (timestamp instanceof Date) ? new Date(timestamp) : // JS Date()        new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int)
        );
        return format.replace(formatChr, formatChrCb);
    };
    return this.date(format, timestamp);}
external links: original PHP docs | raw js source

Examples

» Example 1

Running

1
date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400);

Should return

1
'09:09:40 m is month'

» Example 2

Running

1
date('F j, Y, g:i a', 1062462400);

Should return

1
'September 2, 2003, 2:26 am'

Dependencies

No dependencies, you can use this function standalone.

Open syntax issues

php.js uses JsLint to help us keep our code consistent and prevent some common bugs.

Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.


Authors

Thanks to the following developers, you get to have date goodness in JavaScript.

Comments

Add Comment
Use:
[CODE]
your_stuff('here');
[/CODE]
for proper code formatting
By submitting code here you are allowing us to use it in php.js hence dual licensing it under the MIT and GPL licenses

Gravatar
Chris
29 Dec '11 Permalink

q  The o for ISO-8601 year is wrong!

date, W, o, o should be
2007-12-31, 52, 2006, 2008
2010-01-01, 52, 2011, 2009
2011-01-01, 52, 2012, 2010
2012-01-01, 52, 2013, 2011
2001-12-31, 1, 2000, 2002

Change function for 'o' to:

o: function () { // ISO-8601 year
  var n = f.n(), W = f.W(), Y = f.Y();
  return Y + (n === 12 && W < 9 ? +1 : n === 1 && W > 9 ? -1 : 0);
}

Gravatar
ZERONETA
26 Sep '11 Permalink

q  

var date = function( a, s )
{
	var d = isNaN( s *= 1000 ) ? new date() : new date( s ), f = d.getTime();
	return ( '' + a ).replace( /a|A|d|D|F|g|G|h|H|i|I|j|l|L|m|M|n|s|S|t|T|U|w|y|Y|z|Z/g, function( a )
	{
		switch ( a )
		{
			case 'a' : return d.getHours() > 11 ? 'pm' : 'am';
			case 'A' : return d.getHours() > 11 ? 'PM' : 'AM';
			case 'd' : return ( '0' + d.getDate() ).slice(-2);
			case 'D' : return [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ][ d.getDay() ];
			case 'F' : return [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ][ d.getMonth() ];
			case 'g' : return ( s = ( d.getHours() || 12 ) ) > 12 ? s - 12 : s;
			case 'G' : return d.getHours();
			case 'h' : return ( '0' + ( ( s = d.getHours() || 12 ) > 12 ? s - 12 : s ) ).slice(-2);
			case 'H' : return ( '0' + d.getHours() ).slice(-2);
			case 'i' : return ( '0' + d.getMinutes() ).slice(-2);
			case 'I' : return (function(){ d.setDate(1); d.setMonth(0); s = [ d.getTimezoneOffset() ]; d.setMonth(6); s[1] = d.getTimezoneOffset(); d.setTime( f ); return s[0] == s[1] ? 0 : 1; })();
			case 'j' : return d.getDate();
			case 'l' : return [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ][ d.getDay() ];
			case 'L' : return ( s = d.getFullYear() ) % 4 == 0 && ( s % 100 != 0 || s % 400 == 0 ) ? 1 : 0;
			case 'm' : return ( '0' + ( d.getMonth() + 1 ) ).slice(-2);
			case 'M' : return [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ][ d.getMonth() ];
			case 'n' : return d.getMonth() + 1;
			case 's' : return ( '0' + d.getSeconds() ).slice(-2);
			case 'S' : return [ 'th', 'st', 'nd', 'rd' ][ ( s = d.getDate() ) < 4 ? s : 0 ];
			case 't' : return (function(){ d.setDate(32); s = 32 - d.getDate(); d.setTime( f ); return s; })();
			case 'T' : return 'UTC';
			case 'U' : return ( '' + f ).slice( 0, -3 );
			case 'w' : return d.getDay();
			case 'y' : return ( '' + d.getFullYear() ).slice(-2);
			case 'Y' : return d.getFullYear();
			case 'z' : return (function(){ d.setMonth(0); return d.setTime( f - d.setDate(1) ) / 86400000; })();
			default : return -d.getTimezoneOffset() * 60;
		};
	} );
};

Gravatar
Gotibandhu
23 Sep '11 Permalink

q  Hello Everyone,
We can use Date () object to manipulate dates in java script. Whenever we want to access current date of the system or want to set new date in java script then we can use appropriate java script method of date function. In this demonstration we learn how to work with function of date object.........
For more details check this link.....
http://mindstick.com/Articles/c18de1aa-fd9c-433a-80ea-93c14522c856/?Implementing%20Date%20object%20in%20Java%20Script

Thanks !!!!

Gravatar
Rafał Kukawski
18 Sep '11 Permalink

q  @omid: thanks for your bug report. The function is now fixed on Github (https://github.com/kvz/phpjs/commit/97aa7a53befc80544cd4bdc681deab041cfee779)

Gravatar
omid
18 Sep '11 Permalink

q  O return incorrect format
for example return +0350 instead of +0330
code must change to

var a = jsdate.getTimezoneOffset();
return (a > 0 ? "-" : "+") + _pad(Math.floor(Math.abs(a) / 60) * 100 + Math.abs(a) % 60, 4);

Gravatar

20 Jul '11 Permalink

q  

Gravatar

18 Jul '11 Permalink

q  

Gravatar

17 Jul '11 Permalink

q  

Gravatar

7 Jul '11 Permalink

q  

Gravatar
Frederik Hannibal
22 Jun '11 Permalink

q  FYI: Test #5 fails in node.js

Gravatar

29 May '11 Permalink

q  

Gravatar
Theriault
11 Apr '11 Permalink

q  @Martin: Thanks. Fixed.

Gravatar
Brett Zamir
8 Apr '11 Permalink

q  @Alex Wilson: Thanks very much for the implementation, but by relying on "new Function", it runs a bit more slowly, as well as has some eval-ish concerns.

Gravatar
Alex Wilson
7 Apr '11 Permalink

q  A shorter implementation:

https://gist.github.com/raw/899179/40ef949f244fdbf4103804b870c515e134b611ec/php.date.js

Gravatar
Matteo
5 Apr '11 Permalink

q  I think I found a problem with this function:

date('d-m-Y', strtotime("2012-02-04 +6 WEEK"));



returns 17-05-2011 insted of 17-03-2012 as it should. Or am I doing something wrong?

Gravatar
Martin
21 Mar '11 Permalink

q  Be aware that this implementation will emit non-zero-padded numbers when using "W" whereas php's native implementation does pad the lower numbers.

Gravatar
Matthew Ralston
27 Feb '11 Permalink

q  Looks like there's a bug in date() when using Firefox. It's certainly present on version 4.0b7 on Mac OS X, not sure about other versions.

<script type="text/javascript" src="php.full.min.js"></script>
<script type="text/javascript">

window.onload=function() {
	var myDate='1970-01-01 00:00:00';
	var myTimestamp=strtotime(myDate);
	var myFormattedDate=date('d/m/Y H:i:s', myTimestamp);
	
	alert('myDate: ' + myDate + '\n' + 'myTimestamp: ' + myTimestamp + '\n' + 'myFormattedDate: ' + myFormattedDate);
}

</script>



After applying date(), it incorrectly reports that the hour is 01, instead of 00.

Doesn't seem to be an issue in Safari.

Gravatar
saturn
10 Jan '11 Permalink

q  if the W value less than 9 the value eq X(9>=x>0) can not display 0X(PHP can do);

Gravatar
saturn
10 Jan '11 Permalink

q  In line 147 the code not right.
date('o-W',1293840000);
the result return 2012-52 , php function will return 2010-52.
maybe the code can change to
return Y + (n === 12 && W < 9 ? -1 : n === 1 && W > 9? -1 : 0);
thanks

Gravatar
Brett Zamir
2 Dec '10 Permalink

q  @Nox: Thanks for the submissions. As far as JT's change, I don't have time right now to review; anyone else? As far as Date.prototype, we don't like to pollute the native prototype objects, though I know it can be convenient. As far as internationalization, as per PHP's recommendation (since date() is not localized), we use strftime & setlocale for localization of dates instead (as it provides a clear "PHP way" for us to implement it following the same API and behavior).

Gravatar
Nox
30 Nov '10 Permalink

q  ... Actually I just can't figure out where I should send the modified version... If you like to get it, just send me an email...
Thanks again
Nox

Gravatar
Nox
30 Nov '10 Permalink

q  Hi, just send you an email with a few changes I recommend.

The first one was already made by @JT:

var date = (function() { ... return function(date, timestamp)



The second one is just a way to honor JS...

Date.prototype.format = function (format) {return date(format, this); };



And last but not least I changed to access to the day-strings and month-strings to make it more customizable.

        /*...*/
        F: function () { // Full month name; January...December
            return date.i18n.months[12 + f.n()];
        }
        /*...*/

date.lang = { eng: {
		days: [ /* days start with 0 */ ],
		months: [null, /* months start with 1 */],
		ordin: { /* ... */ }
	}
};
date.i18n = date.lang.eng; // select english



Hope this is useful. If anyone needs my code send me an email.

Thanks for the code, I'm using it serverside on node.js like I was using PHP-date before,
Nox

Gravatar
clinisbut
19 Sep '10 Permalink

q  @Kevin: Thanks, I found the problem: It relates with daylight saving time. So that was my fault. sorry.

Gravatar
Kevin van Zonneveld
8 Sep '10 Permalink

q  @clinisbut: Tested it, but our output exactly matches PHP's.

Here, this snippet runs both in PHP as in the unnamespaced php.js version:

$timestamp = mktime(0, 0, 0, 10, 31, 2010);
$temp = $timestamp + (60*60*24*7);
$string_date = date('d-m-Y', $temp);
print($string_date);

Gravatar
clinisbut
2 Aug '10 Permalink

q  Hi, I'm having an issue with date function.
Starting from a timestamp, I'm adding seven days and converting to string using date() function. Rarely, when I add seven days to 2010-10-31 it gives me 2010-11-6 instead of 2010-11-7.
This is my code

$P = new PHP_JS();
timestamp = $P.mktime( 0, 0, 0,month, day, year );

temp = timestamp + (60*60*24*7);

string_date = $P.date('d-m-Y', temp));



Other dates work fine... is this a bug?

Gravatar
Kevin van Zonneveld
23 Apr '10 Permalink

q  @ Rafał Kukawski: I think I agree. As long as it's 10:00:00 (.9), it still is 10:00:00 and not 10:00:01 implemented your fix, thanks a lot! http://github.com/kvz/phpjs/commit/c3cd2f82d214c4b11edac89d14162fcad3a5675e

Gravatar
Rafał Kukawski
23 Apr '10 Permalink

q  IMO in U() we should do Math.floor instead of Math.round, cause we shouldn't add 1 sec to the result when the millisecond part is just over 500. If you agree, my proposition is

U: function () { // Seconds since UNIX epoch
   return Math.floor(jsdate.getTime() / 1000);
}


or even

U: function () { // Seconds since UNIX epoch
   return jsdate.getTime() / 1000 | 0;
}
U: function () { // Seconds since UNIX epoch
   return jsdate / 1e3 | 0;
}


if you accept less self-explaining code.

Gravatar
Rafal Kukawski
23 Apr '10 Permalink

q  My proposition for checking for leap years would be

L: function(){
   return new Date(jsdate.getFullYear(), 1, 29).getMonth()==1|0;
}



It uses the JS engine to calculate the correct month for February 29 for given year.

Gravatar
Thomas Beaucourt
19 Dec '09 Permalink

q  @Theriault :
Current timezone is Paris GMT+1 (winter / DST off)
Your variant works, provided you throw in a +1 :

z: function (){
    return Math.round((new Date(f.Y(), f.n() - 1, f.j()) - new Date(f.Y(), 0, 1)) / 864e5) + 1;
}

Gravatar
JT
1 Dec '09 Permalink

q  Might help if I had declared jsdate as a var in my post below, I suppose =)

JT

Gravatar
JT
1 Dec '09 Permalink

q  Great work on an incredibly useful function, guys.

Seems like repeatedly declaring the regEx and all of those inner functions every time the date function is called would be pretty inefficient, though. Have you considered doing something like this?

var date = (function () {

    function pad(n, c) {
        ...
    }

    var that      = this,
        formatChr = /\\?([a-z])/gi,
        txt_words = [ ... ],
        txt_ordin = { ... },
        f = {
            w : function (d) {
                return d.getDay();
            },
            ...
        };

    return function (format, timestamp) {
        // Just for clarity :$
        if (timestamp) {
            jsdate = (timestamp instanceof Date) ? new Date(timestamp) : new Date(timestamp * 1000);
        } else {
            jsdate = new Date();
        }

        return format.replace(formatChr, function (t, s) {
            return f[t] ? f[t](jsdate) : s;
        });
    };
}());



JT

Gravatar
Theriault
30 Nov '09 Permalink

q  @Felix: The 'W' function has been updated with a new algorithm. Thank you for your contribution.

@Thomas: I cannot seem to reproduce the bug you are experiencing. What is your system's current timezone offset and what browser are you using? Also, does the following code also fix the problem:

z: function () {
    return Math.round((new Date(f.Y(), f.n() - 1, f.j()) - new Date(f.Y(), 0, 1)) / 864e5);
},

Gravatar
Thomas Beaucourt
26 Nov '09 Permalink

q  The "z" function is buggy.
It doesn't account for daylight saving time when doing :

(jsdate - new Date(jsdate.getFullYear() + "/1/1")) / 864e5



thus it returned 2 days more for '2009-10-25' than for '2009-10-24'.

My fixed function is :


z: function (){
var m = f.n();
var z = 0;
for (i=1; i return z + f.j();
}



Which uses an improved t function accepting a parameter :


t: function (n) {
if (n == undefined) n = jsdate.getMonth() + 1;
if ( n == 2 ) return 28 + f.L();
if ( n & 1 && n < 8 || !(n & 1) && n > 7 ) return 31;
return 30;
}




Thanks for the good work !

Gravatar
Felix Blaschke
12 Nov '09 Permalink

q  Sorry for repost: I mean 2nd january 2006 returns wrong week number.

php.date("W", new Date(2006,0,2)) // correct result would be "1"

Gravatar
Felix Blaschke
12 Nov '09 Permalink

q  The "W" function is wrong. For example for the 2nd january 2005 it returns the wrong weak number. I correct it myself with another algorithm:

        // Week
            W: function () {
            	var x = (new Date(jsdate.getFullYear(), 0, 4))
            	var a = new Date(jsdate.getFullYear(), 0, 4-(x.getDay()==0 ? 7:x.getDay()-1))
        		for (var w=0; w <= 53; w++) {
            		var b = new Date(a.getFullYear(), a.getMonth(), a.getDate()+(w-1)*7, 0,0,0,0)
            		var c = new Date(a.getFullYear(), a.getMonth(), a.getDate()+w*7, 0,0,0,0)
            		if (jsdate >= b && jsdate < c) {break;}
            	}
            	if (w >= 1 && w <= 52) {return w;}
            	if (w >= 52 && w != ((new Date(jsdate.getFullYear(),0,1)).getDay() == 4 ? 53 : 52)) {return 1;}
            	return ((new Date(jsdate.getFullYear(),0,1)).getDay() == 4 ? 53 : 52);
            },

Gravatar
Kevin van Zonneveld
8 Nov '09 Permalink

q  Hey there Theriault!

Blown away by your expertise & quality of code. Let me try to reach you by mail and see if you'd like to append the code another way ; )

If you haven't received my mail drop another line here, ok?

Gravatar
Theriault
8 Nov '09 Permalink

q  The return function at the bottom could be shortened to one line using a ternary operator:

return format.replace(/\\?([a-z])/gi, function (t, s) {return f[t] ? f[t]() : s;});



"I" could not rely on the _dst function up top and be shortened to one line:


return 0 + (t.getTimezoneOffset() < Math.max((new Date(d.Y(), 0, 1)).getTimezoneOffset(), (new Date(d.Y(), 6, 1)).getTimezoneOffset()));



And a bunch of little nitpicky fixes that I can suggest:

txt_weekdays at the top could remove the repeat of 'day' 7 times and just add 'day' to the 'l' (lowercase-L) function:

var txt_weekdays = ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur"];

return txt_weekdays[f.w()] + 'day';



'N' could be like 'g' and use the OR operator to make it a little shorter:

return f.w() || 7;



'S' could also use the OR operator to make it a bit shorter:
return txt_ordin[f.j()] || 'th';

'o' (lowercase O) could be shortened to one line:
return f.Y() + (f.n() == 12 && f.W() < 9 ? -1 : (f.n() == 1 && f.W() > 9 ? 1 : 0));

'M' could be one line:

return f.F().slice(0, 3);



'D' could be one line:

return f.l().slice(0, 3);



Thanks. Keep up the good work PHP.JS.

Gravatar
Theriault
8 Nov '09 Permalink

q  @Brett: I was unsure, but after reviewing ECMA-262, it is a part of the ECMA standards. The standards state that date arguments are to be treated as finite integers and they all support values outside the ranges (such as 13, 1000, or even -500 for the month). The date argument formula is:

Day(Result(7)) + Result(4) − 1.

Day(Result(7)) returns the computed days since Jan 1, 1970 for the current time's year and month, Result(7), plus Result(4) which is the integer date argument, so 0 would add no days to the first of the calculated month and year, then it subtracts one day to account for the first day of the month which was included in the calculation of Result(7), so that would be the previous month's last day.

I would have to say that the algorithm's that ECMA has laid out for date handling are the best I've seen out there; very flexible. To think that Date.setDate(Date.getDate() - 7) subtracts one week exactly, or Date.setMonth(Date.getMonth() - 6) can subtract half a year is fantastic, no matter the date.

However, the way I did it is incorrect. A string argument being passed to the Date constructor may be handled differently by all browsers. 't' should be changed to use 3 integers in the constructor instead:

return (new Date(f.Y(), f.n() + 1, 0).getDate();



I believe I have found the solution to 'W', also. The following should work after reviewing ISO-8601 algorithms for calculating the week. I have confirmed it works from Jan 1 1900 to Dec 32 2100, which is likely enough testing:

return 1 + Math.round(((c = new Date(d.Y(), d.n() - 1, d.j() - d.N() + 3)) - (new Date(c.getFullYear(), 0, 4))) / 864e5 / 7);

Gravatar
Brett Zamir
7 Nov '09 Permalink

q  Does anyone know whether the technique of setting a date to '0' to get the last day of the month (as used in Theriault's 't' implementation) part of the ECMAScript spec or is it just a browser convention?

Gravatar
Kevin van Zonneveld
7 Nov '09 Permalink

q  Hey Theriault, thanks for your improvements. I've just added them to the repo.
http://github.com/kvz/phpjs/commit/0a830484289ece0cebdbf6d2fafe849b9308284b

As for the W: issue, I've added a testcase (#8) that confirms we stray from PHP's behavior there () (but it seems PHP in turn strays from my System's calendar ; ), this will require a quiet sunday afternoon of tesing & fixing though..
If anyone is up for a challenge, that would rock! :D

Gravatar
Theriault
30 Oct '09 Permalink

q  I found a bug with 'W'. For 2010, week 52 runs from 12/27/2010 to 12/31/2010 (only 5 days), then 1/1/2011 is week 53, then 1/2/2011 to 1/3/2011 are the last two days of week 52. Then week 1 is 1/4/2011 to 1/9/2011 (only 6 days). It seems to happen on other dates, too, with some weeks having only 6 days and some having 8 days.

Gravatar
Theriault
25 Oct '09 Permalink

q  't' could be shortened to:

return (new Date((f.n() + 1) + '/0/' + f.Y())).getDate();

Gravatar
Theriault
25 Oct '09 Permalink

q  'B' could be simplified to:

return pad(Math.floor(((t.getUTCHours() * 36e2) + (t.getUTCMinutes() * 60) + t.getUTCSeconds() + 36e2) / 86.4) % 1e3, 3);

Gravatar
Brett Zamir
19 Sep '09 Permalink

q  @Alex: The issue should be fixed now. Our date functions were only accepting "undefined" (or missing) timestamps, numeric timestamps, or JavaScript Date() object timestamps. If they were expressed as a string or other non-object types, there was no attempt to auto-convert them (as PHP does). It seems therefore that your JSON was returning timestamps as strings and not numbers, thus causing a mismatch. However, the latest version in git can handle the strings now too: http://github.com/kvz/phpjs/commits/master/functions/datetime/date.js/8a428dccc64253a59b84b692fbfe323f5e9d29c9 . FYI, you might want to check out https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Operators/Special_Operators#conditional_operator to understand what the code at the beginning of the function is doing when assigning timestamp to a Date object, if you were not clear. Have fun!

Gravatar
Alex
18 Sep '09 Permalink

q  @Brett Don't think it would matter, but my timestamp comes from JSON obtained by jQuery.

Gravatar
Alex
18 Sep '09 Permalink

q  @Brett It was a standard unix timestamp in seconds. (meant to indicate that in my inital post). It appears that the original source code handled a conversion (line 39 in v909.322).

I imagine that was written this way in the first place to handle PHP defaulting to mktime() if the 2nd argument isn't set, but I don't see anywhere where that actually happens, thus if the typeof(timestamp) fails there is no value when the JS Date() methods are called.

Gravatar
Brett Zamir
18 Sep '09 Permalink

q  @Alex: Thanks. Now, what data did you have in "data.ts" and what type (Number, Date object?). And though I don't think it would matter in this case, are you using a Unix timestamp as in seconds (as in PHP), or a JavaScript value in milliseconds?

Gravatar
Alex
18 Sep '09 Permalink

q  I should mention that I first encountered this issue in Chrome 3, and tested my fix in Chrome 3, FF 3.5, IE8, Safari 3.2.2, and Opera 9.64 all on Windows XP.

Gravatar
Alex
18 Sep '09 Permalink

q  I altered the code from the above code (marked as version 909.322 (had the same issue in code marked 2.91)) by deleting lines 37-41 and inserting at line 37:

var jsdate = new Date();
jsdate.setTime(timestamp * 1000);

Gravatar
Brett Zamir
18 Sep '09 Permalink

q  @Alex: As Kevin asked Paul, are you using the latest version? What browser? Have you tried placing alerts within the date() function to see at least where things go wrong?


Contribute a New function

More functions

In this category

checkdate
» date
date_default_timezone_get
date_default_timezone_set
date_parse
getdate
gettimeofday
gmdate
gmmktime
gmstrftime
idate
localtime
microtime
mktime
strftime
strptime
strtotime
time
timezone_abbreviations_list
timezone_identifiers_list

Support us

spread the word:


Use any PHP function in JavaScript


These kind folks have already donated: AYHAN BARI*, Nikita Ekshiyan, Nikita Ekshiyan, Petr Pavel, @HalfWinter, Paulo Freitas, Andros Peña Romo, @andorosu, Raimund Szabo, Nitin Gupta, @nikosdion, Anonymous, Anonymous and Shawn Houser.
<your name here>

Click here to lend your support to: phpjs and make a donation at www.pledgie.com !