Date() converts certain date strings to local time - javascript

I'm trying to compare two date strings for equality by wrapping them with the Date() object. I live in Seattle and for some reason, the second date string is converted to PST and then rendered in GMT, resulting in the below:
new Date("January 1, 2012")
>>> Sun Jan 01 2012 00:00:00 GMT-0800 (PST)
new Date("2012-01-01")
>>> Sat Dec 31 2011 16:00:00 GMT-0800 (PST)
Try the above in the chrome console and you should get the same results.
How do I get Date to evaluate the second statement as GMT instead of PST?

Do not use the Date object to parse date strings, it is specified as implementation dependent in ECMAScript ed 3 and doesn't work consistently across browsers. One format of ISO8601 date string is specified in ES5, but that doesn't work consistently either. Manually parse the string.
A couple of functions to convert to and from UTC ISO8601 strings:
if (!Date.prototype.toUTCISOString) {
Date.prototype.toUTCISOString = function() {
function addZ(n) {
return (n<10? '0' : '') + n;
}
function addZ2(n) {
return (n<10? '00' : n<100? '0' : '') + n;
}
return this.getUTCFullYear() + '-' +
addZ(this.getUTCMonth() + 1) + '-' +
addZ(this.getUTCDate()) + 'T' +
addZ(this.getUTCHours()) + ':' +
addZ(this.getUTCMinutes()) + ':' +
addZ(this.getUTCSeconds()) + '.' +
addZ2(this.getUTCMilliseconds()) + 'Z';
}
}
if (!Date.parseUTCISOString) {
Date.parseUTCISOString = function fromUTCISOString(s) {
var b = s.split(/[-T:\.Z]/i);
var n= new Date(Date.UTC(b[0],b[1]-1,b[2],b[3],b[4],b[5]));
return n;
}
}
var s = '2012-05-21T14:32:12Z'
var d = Date.parseUTCISOString(s);
alert('Original string: ' + s +
'\nEquivalent local time: ' + d +
'\nBack to UTC string: ' + d.toUTCISOString());

Taking robg's advice you might look at DateJS or moment.js

That's because of your time zone, you are 8:00 hours late to the "2012-01-01", so its showing like that, for me i got this
new Date("January 1, 2012")
Sun Jan 01 2012 00:00:00 GMT+0530 (IST)
new Date("2012-01-01")
Sun Jan 01 2012 05:30:00 GMT+0530 (IST)

Related

javascript consistent format of date

I have a function that is expecting the startDate and endDate to be in YYYY-mm-dd format as a (String). Because I'm using a couple components/plugins, sometimes the dates are coming in different formats.
If the date comes in as "Wed Jan 01 2020 00:00:00 GMT-0800" format. I want to convert it into YYYY-mm-dd However, if its already in YYYY-mm-dd format, don't touch it.
I tried using something like where I pass in my initial string, but it seems to be messing up my date because of the inconsistent nature of the startDate value.
var d = new Date(startDate);
var datestring = d.getDate() + "-" + (d.getMonth()+1) + "-" + d.getFullYear() + " " +
d.getHours() + ":" + d.getMinutes();
You can easily achive the data in YYYY-mm-dd format using toISOString and split
function getDate(date) {
return date.match(/^\d{4}-\d{2}-\d{2}$/)
? date
: new Date(date).toISOString().split("T")[0];
}
console.log(getDate("2020-03-12"));
console.log(getDate("Wed Jan 01 2020 00:00:00 GMT-0800"));
console.log(getDate("Wed Dec 01 2020 00:00:00 GMT-0800"));
console.log(getDate("Wed Mar 29 2020 00:00:00 GMT-0800"));

date manipulation in javascript

I have this string for example "November 8, 2016 - December 7, 2016" which I want to extract the two dates in the this format: YYYY-MM-DD.
Now, I managed to get the dates in the format I want in the following way:
HTML:
<span id="selecDate">November 8, 2016 - December 7, 2016</span>
Javascript:
date = $('#selecDate').text().split('-');
begin = new Date(date[1]);
begin = begin.toISOString().split('T')[0];
The problem is that date = ["November 8, 2016 ", " December 7, 2016"]
and begin = "Wed Dec 07 2016 00:00:00 GMT+0200 (IST)"
when in second line but in the last line the value of begin changes to "2016-12-06", one day earlier. Any idea how can I avoid it?
I'm working from (GMT+02:00) time zone
When you execute toISOString() the date you get back is in UTC time so it takes the time back 2 hours (because of your current timezone). Midnight on Dec 06 in IST is 22:00 in UTC time the day before.
If you wish to keep your timestamps in local time, you can use a .toLocaleDateString(), toLocaleString() or even just .toString() on your date object:
begin = new Date('December 7, 2016').toLocaleDateString();
Note that the date format is slightly different:
a.toLocaleDateString()
"12/7/2016"
a.toLocaleString()
"12/7/2016, 12:00:00 AM"
a.toString()
"Wed Dec 07 2016 00:00:00 GMT+0200 (IST)"
As MDN says in, method toISOString():
The timezone is always zero UTC offset.
And when you create your new Date('December 7, 2016'), what you get is:
Wed Dec 07 2016 00:00:00 GMT+0200
So in UTC, the hours are subtracted by 2, giving you the day before.
Solution:
begin = begin.getFullYear() + '-' + (begin.getMonth() + 1) + '-' + begin.getDate();
will result in: "2016-12-07".
date = ["November 8, 2016 ", " December 7, 2016"];
var b = new Date(date[1]);
//use these get methods to avoid all the confusion
var begin = b.getFullYear()+"-"+(b.getMonth()+1)+"-"+b.getDate();
console.log(_begin);
You should not parse strings with the Date constructor, especially when they are a format other than that specified in ECMA-262 as the behaviour is implementation dependent.
If you need Date objects, you should either use a library (e.g. moment.js, fecha.js) and provide the format to parse or write a simple function to parse the format to a date (see below).
However, if you just want a string in a different format, just reformat the string and avoid Dates altogether:
// Reformat a date string in format MMMM d, yyyy to yyyy-mm-dd
function reformatDate(s) {
var b = s.match(/\w+/g) || [];
var months = {jan:'01',feb:'02',mar:'03',apr:'04',may:'05',jun:'06',
jul:'07',aug:'08',sep:'09',oct:'10',nov:'11',dec:'12'};
return b.length == 3? b[2] + '-' +
months[b[0].toLowerCase().substr(0,3)] + '-' +
('0' + b[1]).slice(-2) : '';
}
console.log(reformatDate('November 8, 2016'))
The following functions parse a date in MMMM d, yyyy format to a Date object, then format it in yyyy-mm-dd format:
// Parse date string in format MMMM d, yyyy e.g. November 8, 2016
function parseDate(s) {
var months = 'jan feb mar apr may jun jul aug sep oct nov dec'.split(' ');
var b = s.match(/\w+/g) || [];
var m = months.indexOf(b[0].toLowerCase().substr(0,3));
var d = new Date(b[2], m, b[1]);
return d && d.getMonth() == m? d : new Date(NaN);
}
function toISODate(d) {
function z(n){return (n<10?'0':'')+n}
return d.getFullYear() + '-' + z(d.getMonth()+1) + '-' + z(d.getDate());
}
console.log(toISODate(parseDate('November 8, 2016')))
Using a library like moment.js you'd do:
'November 8, 2016 - December 7, 2016'.split(' - ').forEach(function(s) {
var d = moment(s,'MMMM D, YYYY').format('YYYY-MM-DD');
console.log(d);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.js"></script>

Javascript not parsing dates properly

I have been using some extensions on the Date prototype to perform some operations (Advice: do not do that, it screws the date object; too late for me in my current project) and lately have been having some more issues than usual.
To parse strings in H:m format, I made a custom function and assigned it to the Date prototype like this:
Date.__parse = Date.parse;
Date.parse = function(string){
var pattern = /^\d{1,2}:\d{1,2}/ig;
var today = new Date();
if ( pattern.exec(string) ){
var year = today.getFullYear();
var month = today.getMonth()+1;
var day = today.getDate();
var t = year+"-"+month+"-"+day+" "+string;
var timestamp = Date.__parse(t);
return new Date(timestamp);
}
else{
return new Date(Date.__parse(string));
}
}
Ugly when you try to log the date object but working until recently.
For a time, Date.parse seems to work with dates in "d-m-Y" format, but lately it is returning "invalid date" when I do it.
Did something change in the way major browsers parse the dates, or some change to the specification, or must I assume that the error was there before, and it didn´t trigger "Invalid Date" because I was lucky? (I mostly use the function to validate input fields, so it could very well pass unnoticed).
Guess I will have to write my own date scripts and totally forget the js Date object, it´s really horrible (tried to use moment.js, but the performance in the component where I use it was very poor, that´s why I had to make custom functions).
EDIT
For a better understanding;
What I was doing and seemed to work:
Date.parse("23-7-2016") // Never got an error, expected 23 Jul 2016
What I found after tracking a validation error:
var startDate = Date.parse("23-7-2016");
console.log(startDate.toISOString()); //Got Invalid Date
What I think may have happened
var startDate = Date.parse("12-7-2016");
// expected 12 Jul 2016, got 7 Dec 2016, silently fails, everyone is happy
Why I think the prev. case is not the case: I use an interactive scheduler and performed thousands of tests on it, hardly such an error would go unnoticed.
Worst scenario: chrome updated and changed the way it parses dates.
Not sure... hoped someone could enlighten me.
I've determined your method should work for any valid input. You problem is most likely that your regex is valid for hours above 23, and minutes above 59.
See my jsfiddle, which enumerates all valid inputs. https://jsfiddle.net/kLngLL72/4/
I didn't overwrite the Date.parse function in my example to prevent infinite nesting of the function.
Date.__parse = Date.parse;
var dparse = function(string){
var pattern = /^\d{1,2}:\d{1,2}/ig;
var today = new Date();
if ( pattern.exec(string) ){
var year = today.getFullYear();
var month = today.getMonth()+1;
var day = today.getDate();
var t = year+"-"+month+"-"+day+" "+string;
var timestamp = Date.__parse(t);
return new Date(timestamp);
}
else{
return new Date(Date.__parse(string));
}
}
$("#data").append("<tr><td>" + dparse("01-01-2016 1:31") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("1-1-2016 0:0") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("1-1-2016 12:59") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("1-1-2016 23:59") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("12-31-2016 1:1") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("12-31-2016") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("12-31-2016 24:0") + "</td></tr>");
$("#data").append("<tr><td>" + dparse("12-31-2016 99:99") + "</td></tr>");
for (var i = 0; i < 24; i++)
{
for (var j = 0; j < 60; j++)
{
$("#data").append("<tr><td>" + dparse("12-31-2016 " + i + ":" + j) + "</td></tr>");
}
}
UPDATED - NEW JS FIDDLE https://jsfiddle.net/mfe55xun/2/
This new example, only passes the hour and minute string in.
Date.__parse = Date.parse;
var dparse = function(string){
var pattern = /^\d{1,2}:\d{1,2}/ig;
var today = new Date();
if ( pattern.exec(string) ){
var year = today.getFullYear();
var month = today.getMonth()+1;
var day = today.getDate();
var t = year+"-"+month+"-"+day+" "+string;
var timestamp = Date.__parse(t);
return new Date(timestamp);
}
else{
return new Date(Date.__parse(string));
}
}
$("#data").append("<tr><td>" + dparse("99:99") + "</td></tr>");
for (var i = 0; i < 24; i++)
{
for (var j = 0; j < 60; j++)
{
$("#data").append("<tr><td>" + dparse(i + ":" + j) + "</td></tr>");
}
}
UPDATE
It should be noted that if your input string included the date, the regular Date.parse would work on a string with your H:m formatting:
Date.parse("1/2/2016 4:3")
You would just need to append your "4:3" to a current date string, and you could remove your custom Date.parse function.
Another Update For Updated Question
I don't think that format ever worked correctly for you. It has cases where it will work, but it's always going to interpret the day "23rd" to be a month, and give you an invalid date. Here is another jsfiddle example that loops through all conceivable dates in that format, notice only days 1-12 work. https://jsfiddle.net/mfe55xun/6/
Date.__parse = Date.parse;
var dparse = function(string){
var pattern = /^\d{1,2}:\d{1,2}/ig;
var today = new Date();
if ( pattern.exec(string) ){
var year = today.getFullYear();
var month = today.getMonth()+1;
var day = today.getDate();
var t = year+"-"+month+"-"+day+" "+string;
var timestamp = Date.__parse(t);
return new Date(timestamp);
}
else{
return new Date(Date.__parse(string));
}
}
for (var i = 0; i <= 31; i++)
{
for (var j = 0; j <= 12; j++)
{
$("#data").append("<tr><td>" + i + "-" + j + "-2016 = " + dparse(i + "-" + j + "-2016" ) + "</td></tr>");
}
}
Look at the results loop:
test results
0-0-2016 = Invalid Date
0-1-2016 = Invalid Date
0-2-2016 = Invalid Date
0-3-2016 = Invalid Date
0-4-2016 = Invalid Date
0-5-2016 = Invalid Date
0-6-2016 = Invalid Date
0-7-2016 = Invalid Date
0-8-2016 = Invalid Date
0-9-2016 = Invalid Date
0-10-2016 = Invalid Date
0-11-2016 = Invalid Date
0-12-2016 = Invalid Date
1-0-2016 = Invalid Date
1-1-2016 = Fri Jan 01 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-2-2016 = Sat Jan 02 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-3-2016 = Sun Jan 03 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-4-2016 = Mon Jan 04 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-5-2016 = Tue Jan 05 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-6-2016 = Wed Jan 06 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-7-2016 = Thu Jan 07 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-8-2016 = Fri Jan 08 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-9-2016 = Sat Jan 09 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-10-2016 = Sun Jan 10 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-11-2016 = Mon Jan 11 2016 00:00:00 GMT-0500 (Eastern Standard Time)
1-12-2016 = Tue Jan 12 2016 00:00:00 GMT-0500 (Eastern Standard Time)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
The Date.parse() method parses a string representation of a date, and
returns the number of milliseconds since January 1, 1970, 00:00:00 UTC
or NaN if the string is unrecognised or, in some cases, contains
illegal date values (e.g. 2015-02-31).
It is not recommended to use Date.parse as until ES5, parsing of
strings was entirely implementation dependent. There are still many
differences in how different hosts parse date strings, therefore date
strings should be manually parsed (a library can help if many
different formats are to be accommodated).

Javascript date formatting Fri Jun 21 00:00:00 UTC+0100 2013 to iso 8601 (2013-06-21)

Please advise:
Is there a way without regex or string replaces and so forth to convert a simple date such as:
Fri Jun 21 00:00:00 UTC+0100 2013
To a ISO8601 formatted date yy-mm-dd?
PS: 8601 date only, not date time.
Use moment.js http://momentjs.com/
moment(new Date(), "YYYY-MM-DD HH:mm Z");
or:
var date = moment("Fri Jun 21 00:00:00 UTC+0100 2013");
moment("Fri Jun 21 00:00:00 UTC+0100 2013", "YYYY-MM-DD HH:mm Z");
You can parse it and format it very easily whatever way you want http://momentjs.com/docs/ it is compatible with ISO-8601 dates for parsing as well.
Yes !
the date function in javascript.
var d = new Date("Fri Jun 21 00:00:00 UTC+0100 2013")
alert( d.getFullYear() + '-' + d.getUTCMonth() + '-' + d.getUTCDay())
2 lines of code :)
more info here : http://www.w3schools.com/jsref/jsref_obj_date.asp
Without regexes or string replaces? Yes, assuming that the format is fixed you could use .slice() and/or .substr() to extract the particular bits you need and rearrange them (unless such methods fall into your category of "and so forth"):
var input = "Fri Jun 21 00:00:00 UTC+0100 2013";
var year = input.slice(-4),
month = ['Jan','Feb','Mar','Apr','May','Jun',
'Jul','Aug','Sep','Oct','Nov','Dec'].indexOf(input.substr(4,3))+1,
day = input.substr(8,2);
var output = year + '-' + (month<10?'0':'') + month + '-' + day;
Or you could go ahead and get silly with a regex replace:
var output = input.replace(/^[^\s]+\s([^\s]+)\s(\d+)\s.*(\d{4})$/,function(m,p1,p2,p3) {
var month = ['Jan','Feb','Mar','Apr','May','Jun',
'Jul','Aug','Sep','Oct','Nov','Dec'].indexOf(p1)+1;
return p3 + '-' + (month<10?'0':'') + month + '-' + (p2.length===1?'0':'') + p2;
});
Of course you'd probably want to wrap such code in a reformatDate() method.
(For a "simple" reformatting of a date string, the Date object and its methods aren't particularly helpful unless the starting format is one recognised by Date.parse().)
Why dont you try to use the get functions, like getDate(), getMonth(), etc. For example:
var today = new Date();
var d1 = new Date();
alert(d1);
var date = d1.getDate();
var month = d1.getMonth() + 1;
var year = d1.getFullYear();
Then configure the string the way you want it to appear...!

Convert RFC 822 date to valid Date for javascript

I'm using a script calendar that when I choose a date, it convert it to a new format (yyyy-mm-dd)
It works in most browser but in Firefox and Opera, I get an invalid date format because the format i work with is RFC 822.
I'm looking for a way to convert this date format
example:
Thu Sep 08 2011 12:00:00 GMT-0400 (EDT)
and change it to
2011-09-08
Could that be done in javascript ?
UPDATE
Here's my code trying to replace the (EDT) to nothing
$(".taskDate").datepick({
onSelect: function(selectedDate){
selectedDate = selectedDate.replace(/ \(.+\)/, '');
//alert(selectedDate);
var newDate = new Date(selectedDate);
$(".selectedDate").text(newDate.getFullYear()+'-'+(newDate.getMonth()+1)+'-'+newDate.getDate());
location.href="index.php?date="+newDate.getFullYear()+'-'+(newDate.getMonth()+1)+'-'+newDate.getDate();
}
});
Now I get an error
selectedDate.replace is not a function
How come ?
UPDATE 2
Fixed it because it seems that it was an object and not a darn string.
Added
selectedDate = selectedDate.toString();
before the new Date();
Now it's working for all browsers...
Works in Firefox6, see my jsfiddle.
var sOriginalDate = 'Thu Sep 08 2011 12:00:00 GMT-0400 (EDT)';
var oDate = new Date(sOriginalDate);
var iMonth = oDate.getMonth() + 1;
var iDay = oDate.getDate();
var sNewDate = oDate.getFullYear() + '-'
+ (iMonth < 10 ? '0' : '') + iMonth + '-'
+ (iDay < 10 ? '0' : '') + iDay;
alert(sNewDate);
Since the date is RFC 822 you could parse it to a valid Date (the ending EDT does not affect the result):
var dateAsDateObject = new Date(Date.parse(dateInRFC822Format));
This will work with dateInRFC822Format equal to either "Thu Sep 08 2011 12:00:00 GMT-0400 (EDT)" or "Thu Sep 08 2011 12:00:00 GMT-0400"
Now you can get the info you require from dateAsDateObject:
year: dateAsDateObject.getFullYear()
month: dateAsDateObject.getMonth()
day: dateAsDateObject.getDay()
Note: for formatting, if you don't mind using jqueryui you could also use the $.datepicker.formatDate() method. E.g. var stringRepresentation = $.datepicker.formatDate('yy-mm-dd', dateAsDateObject);
Try:
var mydate = new Date(originaldate);
mydate = mydate.getYear() + '-' + (mydate.getMonth() + 1) + '-' + mydate.getDate();

Categories