Use PHP functions in JavaScript

JavaScript strtotime

Convert string representation of date and time to a timestamp

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
185
function strtotime (str, now) {
    // Convert string representation of date and time to a timestamp  
    // 
    // version: 1109.2015
    // discuss at: http://phpjs.org/functions/strtotime    // +   original by: Caio Ariede (http://caioariede.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: David
    // +   improved by: Caio Ariede (http://caioariede.com)
    // +   improved by: Brett Zamir (http://brett-zamir.me)    // +   bugfixed by: Wagner B. Soares
    // +   bugfixed by: Artur Tchernychev
    // %        note 1: Examples all have a fixed timestamp to prevent tests to fail because of variable time(zones)
    // *     example 1: strtotime('+1 day', 1129633200);
    // *     returns 1: 1129719600    // *     example 2: strtotime('+1 week 2 days 4 hours 2 seconds', 1129633200);
    // *     returns 2: 1130425202
    // *     example 3: strtotime('last month', 1129633200);
    // *     returns 3: 1127041200
    // *     example 4: strtotime('2009-05-04 08:30:00');    // *     returns 4: 1241418600
    var i, match, s, strTmp = '',
        parse = '';
 
    strTmp = str;    strTmp = strTmp.replace(/\s{2,}|^\s|\s$/g, ' '); // unecessary spaces
    strTmp = strTmp.replace(/[\t\r\n]/g, ''); // unecessary chars
    if (strTmp == 'now') {
        return (new Date()).getTime() / 1000; // Return seconds, not milli-seconds
    } else if (!isNaN(parse = Date.parse(strTmp))) {        return (parse / 1000);
    } else if (now) {
        now = new Date(now * 1000); // Accept PHP-style seconds
    } else {
        now = new Date();    }
 
    strTmp = strTmp.toLowerCase();
 
    var __is = {        day: {
            'sun': 0,
            'mon': 1,
            'tue': 2,
            'wed': 3,            'thu': 4,
            'fri': 5,
            'sat': 6
        },
        mon: {            'jan': 0,
            'feb': 1,
            'mar': 2,
            'apr': 3,
            'may': 4,            'jun': 5,
            'jul': 6,
            'aug': 7,
            'sep': 8,
            'oct': 9,            'nov': 10,
            'dec': 11
        }
    };
     var process = function (m) {
        var ago = (m[2] && m[2] == 'ago');
        var num = (num = m[0] == 'last' ? -1 : 1) * (ago ? -1 : 1);
 
        switch (m[0]) {        case 'last':
        case 'next':
            switch (m[1].substring(0, 3)) {
            case 'yea':
                now.setFullYear(now.getFullYear() + num);                break;
            case 'mon':
                now.setMonth(now.getMonth() + num);
                break;
            case 'wee':                now.setDate(now.getDate() + (num * 7));
                break;
            case 'day':
                now.setDate(now.getDate() + num);
                break;            case 'hou':
                now.setHours(now.getHours() + num);
                break;
            case 'min':
                now.setMinutes(now.getMinutes() + num);                break;
            case 'sec':
                now.setSeconds(now.getSeconds() + num);
                break;
            default:                var day;
                if (typeof(day = __is.day[m[1].substring(0, 3)]) != 'undefined') {
                    var diff = day - now.getDay();
                    if (diff == 0) {
                        diff = 7 * num;                    } else if (diff > 0) {
                        if (m[0] == 'last') {
                            diff -= 7;
                        }
                    } else {                        if (m[0] == 'next') {
                            diff += 7;
                        }
                    }
                    now.setDate(now.getDate() + diff);                }
            }
            break;
 
        default:            if (/\d+/.test(m[0])) {
                num *= parseInt(m[0], 10);
 
                switch (m[1].substring(0, 3)) {
                case 'yea':                    now.setFullYear(now.getFullYear() + num);
                    break;
                case 'mon':
                    now.setMonth(now.getMonth() + num);
                    break;                case 'wee':
                    now.setDate(now.getDate() + (num * 7));
                    break;
                case 'day':
                    now.setDate(now.getDate() + num);                    break;
                case 'hou':
                    now.setHours(now.getHours() + num);
                    break;
                case 'min':                    now.setMinutes(now.getMinutes() + num);
                    break;
                case 'sec':
                    now.setSeconds(now.getSeconds() + num);
                    break;                }
            } else {
                return false;
            }
            break;        }
        return true;
    };
 
    match = strTmp.match(/^(\d{2,4}-\d{2}-\d{2})(?:\s(\d{1,2}:\d{2}(:\d{2})?)?(?:\.(\d+))?)?$/);    if (match != null) {
        if (!match[2]) {
            match[2] = '00:00:00';
        } else if (!match[3]) {
            match[2] += ':00';        }
 
        s = match[1].split(/-/g);
 
        for (i in __is.mon) {            if (__is.mon[i] == s[1] - 1) {
                s[1] = i;
            }
        }
        s[0] = parseInt(s[0], 10); 
        s[0] = (s[0] >= 0 && s[0] <= 69) ? '20' + (s[0] < 10 ? '0' + s[0] : s[0] + '') : (s[0] >= 70 && s[0] <= 99) ? '19' + s[0] : s[0] + '';
        return parseInt(this.strtotime(s[2] + ' ' + s[1] + ' ' + s[0] + ' ' + match[2]) + (match[4] ? match[4] / 1000 : ''), 10);
    }
     var regex = '([+-]?\\d+\\s' + '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?' + '|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday' + '|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday)' + '|(last|next)\\s' + '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?' + '|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday' + '|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday))' + '(\\sago)?';
 
    match = strTmp.match(new RegExp(regex, 'gi')); // Brett: seems should be case insensitive per docs, so added 'i'
    if (match == null) {
        return false;    }
 
    for (i = 0; i < match.length; i++) {
        if (!process(match[i].split(' '))) {
            return false;        }
    }
 
    return (now.getTime() / 1000);
}
external links: original PHP docs | raw js source

Examples

» Example 1

Running

1
strtotime('+1 day', 1129633200);

Should return

1
1129719600

» Example 2

Running

1
strtotime('+1 week 2 days 4 hours 2 seconds', 1129633200);

Should return

1
1130425202

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 strtotime 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
Tom
28 Dec '11 Permalink

q  echo(date("Y-m-d H:i:s", strtotime("last monday", 1325050486)));

gives: 2011-11-28 06:34:46
expected: 2011-12-26 00:00:00

Gravatar
Daniele
11 Oct '11 Permalink

q  I am using this function on something mission-critical for the user (an online task manager and calendar) so I need it to be flawless.

I am trying to find bugs and fix them myself. If you want to help me, please contact me.

I would also like to contribute to the Github repo with my fixes - how can I do that?

Here is another bug:

date("Y-m-d", strtotime('+3 days')); // returns 2011-10-14
date("Y-m-d", strtotime('+3 days', 1324815132)); // returns 2011-10-14

I have fixed the bug by replacing line 30 of the version version: 1109.2015 with:
} else if ((!now) && !isNaN(parse = Date.parse(strTmp))) {

I hope that won't introduce new bugs.

Any ideas?

Gravatar
Daniele
11 Oct '11 Permalink

q  This function would be so useful if it was reliable

An example:

PHP
date("Y-m-d", strtotime('second Monday October 2011'));
returns: 2011-10-10
(which is right)

JS:
date("Y-m-d", strtotime('second Monday October 2011'));
returns: 1970-01-01
(which is obviously wrong)

Any solution, suggestion, work around?

Is this function still maintained? If not, maybe I can start working with somebody to maintain it back.

Gravatar
Brad Ramsey
4 Oct '11 Permalink

q  I don't understand why 2011-10-03 is not the same as 10/03/2011... so I patched the function after line 25:

[CODE]
match = strTmp.match(/^(\d{4})-(\d{2})-(\d{2})$/);
if (match != null) {
strTmp = match[2] + '/' + match[3] + '/' + match[1];
}
[CODE]

Worked for me.

Gravatar
Romaric
8 Aug '11 Permalink

q  Hi everybody

Nice function, I've used it a lot, but encountered a few issues :
- it seems unable to decode YYYYMMDD format (not really bad, just use a regex)
- in French, there are accented chars in month names. But when using short names, it will truncate the html char, i.e. AO& instead of AOÛ. I came up with this fix, using html_entity_decode (you may want to apply it to week days, too) :

        M: function () { // Shorthand month name; Jan...Dec
        	// Romaric : using html_entity_decode to avoid bugs with accented chars
        	var _month = f.F();
        	_month = html_entity_decode(_month);
            return _month.slice(0, 3);
        },

Gravatar
Brett Zamir
28 Jul '11 Permalink

q  Yeah. Date.parse() is now apparently treating "11" as 1911. And since Date.parse() might vary across browsers, we should I think be using our own implementation anyways rather than allowing for different behavior by browser. Thoughts?

Gravatar
Jason
28 Jul '11 Permalink

q  Try this in Firefox 5:

console.log(strtotime("06/28/2011"));
console.log(strtotime("06/28/11"));



You get

1309237200
-1846522800



It isn't properly detecting 2 digit years.

Gravatar
Zubin Khavarian
24 Jun '11 Permalink

q  There seems to be a bug where different date formats return different values, try:

strtotime('2011-06-24'); //1308873600
strtotime('06/24/2011'); //1308891600

date('D M j, Y', strtotime('2011-06-24')); //Thu Jun 23, 2011
date('D M j, Y', strtotime('06/24/2011')); //Fri Jun 24, 2011

Gravatar
Scott Connerly
9 Dec '10 Permalink

q  When parsing ISO 8601 dates, PHP's strtotime() doesn't care if there's a colon in the GMT-06:00. php.js's version requires the colon to be there. This most notably comes into play with Facebook's open social graph dates, it won't parse them unless you insert the colon.

Gravatar
Tommy
10 Nov '10 Permalink

q  hello,
this function doesnt support format like this:

2010-11-10T13:34:00+01:00

Gravatar
Brett Zamir
29 Aug '10 Permalink

q  @Brad: I think it is most likely a timezone issue. Our date function currently does not support the setting of a default timezone (as PHP also allows and recommends), so there may be some problem in setting date values according to the browser locale and then using such values across our functions.

You can see "raw js source", note #2, on the date function for the latest notes about how this could be implemented if you are able to make the changes to our code yourself (sorry, I have no time at the moment). Anyone else feel free to help out if you can.

Gravatar
Brad
28 Aug '10 Permalink

q  When I run

date("F j, Y", strtotime("2010-08-03"));


I get "August 2, 2010"

Gravatar
Kevin van Zonneveld
17 Aug '10 Permalink

q  test

Gravatar
Brett Zamir
16 Aug '10 Permalink

q  @Jack: The syntax highlighting code here is buggy, so when you copy-paste it directly, some lines will be commented out. Go to "raw js source" to make sure you have a good copy...It is working with the right code...

Gravatar
Jack
16 Aug '10 Permalink

q  Example 4 returns NaN. Seems to be broken!

Gravatar
Mike
2 Apr '10 Permalink

q  hmm - couple of bugs in strtotime...
1) strtotime('last Monday',now) returns last month not last monday - first 3 letters of month is the same as monday!
work around :

strtotime('last Tuesday, -1 day',now);  // = last monday



2) strtotime('d-m-Y',now) isn't handled correctly (only 'Y-m-d' is) (as mentioned in other comments)
3) in 2 above, the d and m have to be zero padded to work I.E. strtotime('2010-3-1') has to be replaced with ('2010-03-01')
work around :


//examples from variable passed into function perhaps
day = 2;
month = 5;
year = 2010;

if (day < 10) dayzeropad = '0'; else dayzeropad = '';
if (month < 10) monthzeropad = '0'; else monthzeropad = '';
var tstring = year + '-' + monthzeropad + month + '-' + dayzeropad + day;
unixtime = strtotime(tstring);



bugs work-aroundable... cool stuff - thanks.

Gravatar
Zahlii
10 Mar '10 Permalink

q  Is it possible to add support for german-like Dates ?

in PHP (5.3+), strototime('22.01.2010'); works as expected, but not with this js strtotime-method.

Gravatar
Kevin van Zonneveld
14 Dec '09 Permalink

q  @ rav3n: You might be better off parsing your string first before feeding it to strtotime cause I believe PHP wouldn't support your format either.

@ iwosz: Sorry no IE7 on my machine. So unless someone else can get to the bottom of this I may have to see if I can find some WinXP virtual image with IE7 installed or sth like that

Gravatar
iwosz
9 Dec '09 Permalink

q  Under IE 7 strtotime('2009-12-09 12:45:16') returns NaN, can you explain that? some solutions? thx.

Gravatar
rav3n
1 Dec '09 Permalink

q  this function is great. however i need to format the string not as %Y-%m-%d but as %d-%m-%Y.

i understand that it's around line 150-170

Gravatar
Kevin van Zonneveld
9 Oct '09 Permalink

q  @ Daniel Janesch & Theriault: Thanks for pointing out these problems. I've contacted the original author by mail.

Gravatar
Daniel Janesch
8 Oct '09 Permalink

q  First of all: Great work :-)
I have figured out that the following is not working correctly:

$d = new Date(2012, 11, 1, 7, 0, 0);
$r = strtotime('3 Wednesday', $d.getTime()/1000); // 2012-11-01 07:00:00


The correct result with php is 2012-11-21 00:00:00 but with phpjs I get 1351753200 wich is 2012-11-01 07:00:00.
Any clues?

Gravatar
Theriault
6 Oct '09 Permalink

q  PHP seems to apply the string as a whole and not from left-to-right as in this function. In the following PHP example, both $a and $b will be the same date. If PHP applied them from left-to-right, $b would be 2012-03-01, not 2012-02-29.

$d = strtotime('2011-02-22');
$a = strtotime('+1 year, +7 days', $d); // 2012-02-29
$b= strtotime('+7 days, +1 year', $d); // 2012-02-29


This function applies the string from left-to-right, which seems more logical, but is incorrect.

Gravatar
Theriault
4 Oct '09 Permalink

q  I noticed that none of the following work with this function:

today (same as 'now' but resets to 12:00:00AM), tomorrow (same as '+1 day' but also resets to 12), yesterday (same as '-1 day' but also resets to 12).

next week, last week (Currently returns date plus/minus seven days, should return next monday if I remember correctly on how it works in PHP).

last sunday of next month (returns next month, but not last sun/sat/mon/day... of that month)

YYYY-Wnn-d (Basically, sets year to YYYY, week number to nn, and then day of that week to d (0-6). Day of week may be omitted and also overflow, such as 7 for next week.)

00:00:00 (Changes time to 12:00:00 AM or anything else entered here.)


Does anyone else see anything missing from this function? I may recode it. I would like to see it complete -- it is a great function.

Gravatar
Brett Zamir
17 Aug '09 Permalink

q  @majak: Yeah, thanks, it seemed that way from the code snippet (figured out what was the problem by finding that code by Google). Be careful using Prototype or other libraries that overload the prototype objects--it causes problems like these...

Gravatar
majak
17 Aug '09 Permalink

q  @Brett Zamir: Thank you for your help. Your fix works.
Just for reference, I'm using Prototype framework.

Gravatar
Brett Zamir
12 Aug '09 Permalink

q  @majak, it appears you are using a library which overloads the Object prototype with its own functions which this PHP.JS function then iterates... You can solve this problem by adding right after line 184 (see above) the following line (and then the closing brace after line 187):

if (match.hasOwnProperty(i)) {



If you need to work with older browsers like IE 5, you can add this instead:

if (typeof match[i] !== 'function') {



See http://yuiblog.com/blog/2006/09/26/for-in-intrigue/ for a fuller explanation of why.

All of our for...in statements should really use such a test, though since it is cumbersome, and libraries should, imo, really not be altering the prototype in the first place, I think it is a toss-up as to whether we should add these checks ourselves. What do you think, Kevin? Perhaps we should in order to be most compatible...

Gravatar
majak
12 Aug '09 Permalink

q  I'm using the latest (2.85) minified and namespaced version of this function. This snippet:

$P.strtotime('+1 day');


produces TypeError. I have tested it in both FF and Chrome, here are their error messages:

FF:
TypeError: match[i].split is not a function

Chrome:
TypeError: Object function (inline) {
return (inline !== false ? this : this.toArray())._reverse();
} has no method 'split'

I suppose it happens on every relative date string input, like "-3 months".

Gravatar
Brett Zamir
27 Jun '09 Permalink

q  The function expects a string--you are mostly passing something to the function which is not a string.

Gravatar
Andrew
27 Jun '09 Permalink

q  Getting an error --

Error: strTmp.replace is not a function



The debugger is pointing to this line --

strTmp = strTmp.replace(/\s{2,}|^\s|\s$/g, ' '); // unecessary spaces

Gravatar
Kevin van Zonneveld
22 Mar '09 Permalink

q  @ Jeppe: Well that's an issue that should actually have been fixed already. Are you sure you're running the latest version? Thanks!

Gravatar
Jeppe
16 Mar '09 Permalink

q  strtotime("last month"), "-1 month", "next month", etc. doesn't work. Any ideas?
Thanks!

Gravatar
Kevin van Zonneveld
25 Feb '09 Permalink

q  @ Dave: I've contacted the original author Caio Ariede, and he's been kind enough to fix this function up. All testcases work now!


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 !