I've noticed an issue with some data I'm processing (2000+ lines of data).
The problem is very strange: the code works fine! UNTIL a specific date is reached (in this case 01/08/2011) when JavaScript fails to generate the correct date?
So, to explain: I'm taking a string in the format of 'dd/mm/yyyy' and doing (which doesn't work):
var date = '01/08/2011'.split('/');
var milliseconds = new Date(date[2], parseInt(date[1]) - 1, date[0]).getTime(); => 1291161600000
new Date(1291161600000); => Wed Dec 01 2010 00:00:00 GMT+0000 (GMT)
...but yet that exact code works fine with any date before the 1st August 2011?
So try again with 29/07/2011...
var date = '29/07/2011'.split('/');
var milliseconds = new Date(date[2], parseInt(date[1]) - 1, date[0]).getTime(); => 1311894000000
new Date(1311894000000); => Fri Jul 29 2011 00:00:00 GMT+0100 (BST)
The only difference is the (GMT) and (BST) values returned, which suggests a locale issue. But why would that occur, and how can I fix the code to work around that?
Many thanks for any help you can give me.
You are doing octal!
Use a radix!
parseInt(date[1],10)
From the MDN Docs parseInt(string[, radix]):
If radix is undefined or 0, JavaScript assumes the following:
If the input string begins with "0x" or "0X", radix is 16 (hexadecimal).
If the input string begins with "0", radix is eight (octal). This feature is non-standard, and some implementations deliberately do not
support it (instead using the radix 10). For this reason always
specify a radix when using parseInt.
If the input string begins with any other value, the radix is 10 (decimal).
Related
I have date strings like Sun May 10 2020 13:00:00 GMT-0800 (Pacific Standard Time) and 2020/05/10 13:00:00. I would like to retrieve the hour from these string in 24 hour format (in this case it would be, 13).
I have tried something like new Date('Sun May 10 2020 13:00:00 GMT-0800 (Pacific Standard Time)').getHours() but that first converts the hour to system's current timezone and then returns the hour. Instead, I need to be able to retrieve the literal hour from variously formatted date strings such as the two above examples.
Edit: Obviously the above is not the correct approach, what I'm asking is, is there a universal way to parse the hour out of a date string, whether it be the above two examples or others, and without regex?
I am trying to parse a date in JavaScript, but the particular format is giving me fits. I have exported data from my credit card company and the format of the date field is not compatible with Date.parse or moment().isValid().
E.g.
Date.parse("01/01/2016 Fri") // NaN
moment("01/01/2016 Fri") // false
I'm not sure if I should do something with a RegEx .test() or .matches() because this is being used for a CSV import utility where dates may be in different formats. I was surprised the utility functions above didn't work.
Look in the Moment docs to see how to parse a date in any format. The first argument is the date string, the second is the format string. Alphanumeric characters are ignored, so you don't need to worry about slashes vs. dashes.
moment("01/01/2016 Fri", "MM-DD-YYYY ddd)
Check out the Mozilla MDN on Date.parse():
The parse() method takes a date string (such as "Dec 25, 1995") and
returns the number of milliseconds since January 1, 1970, 00:00:00
UTC. This function is useful for setting date values based on string
values, for example in conjunction with the setTime() method and the
Date object.
Given a string representing a time, parse() returns the time value. It
accepts the RFC2822 / IETF date syntax (RFC2822 Section 3.3), e.g.
"Mon, 25 Dec 1995 13:30:00 GMT". It understands the continental US
time zone abbreviations, but for general use, use a time zone offset,
for example, "Mon, 25 Dec 1995 13:30:00 +0430" (4 hours, 30 minutes
east of the Greenwich meridian).
From this, it looks like your problem is that you're giving the date in the improper format:
It
accepts the RFC2822 / IETF date syntax (RFC2822 Section 3.3), e.g.
"Mon, 25 Dec 1995 13:30:00 GMT".
Check this out:
Invalid values in date strings not recognized as ISO format as defined by ECMA-262 may or may not result in NaN, depending on the browser and values provided, e.g.:
// Non-ISO string with invalid date values
new Date('23/25/2014');
TL;DR - you're passing the values in a format that is not recognized, which is why it's returning NaN.
Try this source for Regexes for dates: Regexlib.com. The site is a little out of date, but the info is great. It has tons of different Regexes for different date formats.
I encountered some strange behaviour, and while I don't really have an issue with it, I would like to know the reasoning behind it.
I wrote the following statements:
console.log(new Date("0000-1-1"));
console.log(new Date("0000-01-01"));
console.log(new Date("0000-01-01T00:00:00Z"));
console.log(new Date(0, 0, 1));
While all dates "appear" to be similar, and if you use normal days/months/years behave the same, it does not in this case.
The results are the following:
Sat Jan 01 2000 00:00:00 GMT+0100 (CET)
Sat Jan 01 0 01:00:00 GMT+0100 (CET)
Sat Jan 01 0 01:00:00 GMT+0100 (CET)
Mon Jan 01 1900 00:00:00 GMT+0100 (CET)
Which is quite interesting to me. I can agree with the last one, because the JavaScript spec clearly says the following:
year
Integer value representing the year. Values from 0 to 99 map to the years 1900 to 1999. See the example below.
I can also understand the second and third result, since this is depending on the RFC 2822. They do accept 4*DIGITS as a year, so 0000 should be the year 0 by the RFC spec (I didn't read it completely though).
It's only a bit weird that one of the Date constructors can be used for dates above 1900 while the other constructor allows dates from a wider range (RFC).
However, I do not understand the first result. Where does the year 2000 come from? I do understand that the date is not really an appropriate one, but shouldn't it return Invalid Date in stead of this date?
This is browser specific.
This is yet another area where JavaScript and browser inconsistency cause extra programmer pain. Some browsers will interpret all two digit years as 19xx, so new Date('1/1/49') gives January 1st, 1949, and new Date('1/1/50') gives January 1st, 1950. Others use 1950 as the "two digit year cutoff date", so new Date('1/1/49') gives January 1st, 2049, and new Date('1/1/50') gives January 1st, 1950.
— Two Digit Years in JavaScript - Chris Bristol
You have to bear in mind that the RFC document you've referenced was published in April 2001. The 1900s had only just ended. I guess in an attempt to modernise dates away from the 1900s, some browsers now map 0 to 49 as 2000 to 2049. 50, however, still gets mapped as 1950.
The article quoted above also goes on to give some test results:
Here is a brief summary of the results:
IE9: No two digit year cutoff found. Year 00 = 1900.
Chrome 24.0: Two digit years change between 49 and 50. Year 00 = 2000.
Opera: No two digit year cutoff found. Year 00 = 1900.
Firefox: No two digit year cutoff found. Year 00 = 1900.
Safari: Two digit years change between 49 and 50. Year 00 = 2000.
The article is quite dated now though, so I imagine the data for Opera and Firefox above may have changed.
(new Date('2012-12-01')).getMonth() is 10 instead of 11 (getMonth is 0-indexed). I've tested on Firefox, Chrome, and Node.js. Why does this happen?
You are experiencing a timezone issue. Your JS engine interprets the string as UTC, since it was no further specified. From the specification of Date.parse (which is used by new Date):
The String may be interpreted as a local time, a UTC time, or a time in some other time zone, depending on the contents of the String. The function first attempts to parse the format of the String according to the rules called out in Date Time String Format (15.9.1.15). If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
In your timezone, the datetime is Nov 30 2012 19:00:00 GMT-0500 - in November. Use .getUTCMonth() and you would get December. However, never trust Date.parse, every browser does it differently. So if you are not in a restricted environments like Node.js, you always should parse your string (e.g. with regex) and feed it to new Date(Date.UTC(year, month, date, …)).
For Firefox's case, at least, RFC2822 states that date specifications must be separated by Folding White Space. Try (new Date('2012 12 01')).getMonth(); Usage of - as a separator does not appear to be defined.
The error is arising from prefixing the day 01 with 0. Not sure WHY this is, but if you remove the zero before the 1, it gives you the right month (11).
Also, it starts giving the wrong month at October if that means anything.
Short term fix, use 1 instead of 01.
This morning I noticed a peculiar issue with the JavaScript setFullYear method.
When using the method like so:
d.setFullYear(2012,2,8);
The correct value is returned:
Thu Mar 08 2012 10:30:04 GMT+0000 (GMT Standard Time)
However if I use the parseInt method to return the integers, the date returned is incorrect:
d.setFullYear(parseInt("2012"), parseInt("02"), parseInt("08"));
returns:
Wed Feb 29 2012 10:31:30 GMT+0000 (GMT Standard Time)
It appears that the parseInt method is returning the incorrect values, but when I test it:
document.write(parseInt("2"));
Then the correct value is returned (2)
A working fiddle is here: http://jsfiddle.net/rXByJ/
Does the problem lie with parseInt or with setFullYear?
The problem is that parseInt('08') is 0. This works:
d.setFullYear(parseInt("2012"), parseInt("02"), 8);
Both parseInt('08') and parseInt('09') return zero because the
function tries to determine the correct base for the numerical system
used. In Javascript numbers starting with zero are considered octal
and there's no 08 or 09 in octal, hence the problem.
http://www.ventanazul.com/webzine/articles/issues-parseint-javascript
Solution is to use the second parameter:
parseInt('08', 10)
Or
Number('08')
Also see How do I work around JavaScript's parseInt octal behavior?
This post here on stackoverflow has a very detailed explanation on why one should use parseInt with a base or radix
yes thats true parseInt('08') will return 0 instead of 8 because it takes 08 as octal number and converts into 0 so you should use parseInt('08', 10) where second parameter specifies base for conversion, that is 10 for decimal
so in short always specify base when using parseInt :)
If you are Ok with overriding Date.prototype.setFullYear() function so that it will return a date object instead of milliseconds you can do this.
Date.prototype.setFullYear = (function(ref){
return function(val){
return new Date(ref.bind(this)(val));
}
})(Date.prototype.setFullYear)