Parse javascript date with consistent timezone interpretation? - javascript

Let's say I have two different types of date strings - a mysql date stamp, and a mysql date+time stamp.
"2015-12-25"
"2015-12-25 00:00:00"
When I parse these in JavaScript, I get:
new Date("2015-12-25");
Thu Dec 24 2015 19:00:00 GMT-0500 (Eastern Standard Time)
new Date("2015-12-25 00:00:00");
Fri Dec 25 2015 00:00:00 GMT-0500 (Eastern Standard Time)
Or, in UTC:
new Date("2015-12-25").toUTCString();
"Fri, 25 Dec 2015 00:00:00 GMT"
new Date("2015-12-25 00:00:00").toUTCString();
"Fri, 25 Dec 2015 05:00:00 GMT"
Adding the time on the end somehow makes the date parse as being my-time-zone hours ahead. What I want is some kind of function to make these both parse as the same thing - GMT or no, I can adjust, as long as the outcome is known to be one or the other, no matter the date string passed in.
I got halfway through implementing a solution involving regexes and detecting date format before I figured that there is probably a better way to go about this.
I've found some solutions involving Date.prototype.getTimezoneOffset(), but for both of these dates that returns the same thing, since they are parsed as being in the same timezone.
Any ideas?

ECMAScript ed 5.1 (aka ES5) required that ISO 8601 date strings be parsed as UTC, however ISO required them to be parsed as local. Now the current ECMAScript standard (version 6) is consistent with ISO and requires ISO compliant strings with no timezone to be parsed as local.
<update> ECMAScript 2016 (ed 7) changed again so that YYYY-MM-DD format date strings are parsed as UTC, so no longer consistent with ISO 8601.</update>.
So whether you get one behaviour or the other depends on the browser (and if you try it with IE 8 you'll get NaN). Prior to ES5, parsing of all strings was implementation dependent.
"2015-12-25" is a valid ISO 8601 string with no timezone, so should be treated as UTC under ES5 rules and local by ed 6 rules.
"2015-12-25 00:00:00" is not a valid ISO string (missing the "T" between the date and time) so browsers can parse it however they like (parsing of non–ISO strings is implementation dependent in all versions of ECMAScript).
The bottom line is do not use the Date constructor to parse strings (or Date.parse). Parse them yourself.
To parse ISO-like strings, use something like the following. It treats strings with not offset as UTC (per ES5), however perhaps that should now be changed to be local:
/**
* Parse an ISO string with or without an offset
* e.g. '2014-04-02T20:00:00-0600'
* '2014-04-02T20:00:00Z'
* '2014-02'
*
* Allows decimal seconds if supplied
* e.g. '2014-04-02T20:00:00.123-0600'
*
* If no offset is supplied (or it's Z), treat as UTC (per ECMA-262)
*
* If date only, e.g. '2014-04-02' or '2014-02', treat as UTC date (per ECMA-262)
* All parts after year are optional
* Don't allow two digit years to be converted to 20th century years
* #param {string} s - ISO 860 date string
*/
function parseISOString(s) {
var invalidDate = new Date(NaN);
var t = s.split(/\D+/g);
var hasOffset = /[-+]\d{4}$/.test(s);
// Whether decimal seconds are present changes the offset field and ms value
var hasDecimalSeconds = /[T ]\d{2}:\d{2}:\d{2}\.\d+/i.test(s);
var offset = hasDecimalSeconds? t[7] : t[6];
var offSign;
var yr = +t[0],
mo = t[1]? --t[1] : 0,
da = +t[2] || 1,
hr = +t[3] || 0,
min = +t[4] || 0,
sec = +t[5] || 0,
ms = hasDecimalSeconds? +t[6] : 0,
offSign = hasOffset? /-\d{4}$/.test(s)? 1 : -1 : 0,
offHr = hasOffset? offset/100 | 0 : 0,
offMin = hasOffset? offset%100 : 0;
// Ensure time values are in range, otherwise invalid date.
// Values can't be -ve as splitting on non-digit character
if (hr > 24 || min > 59 || sec > 59 || ms > 1000 || offHr > 24 || offMin > 59){
return invalidDate;
}
// Create a date object from date parts, check for validity
// Avoid two digit years being converted to 20th century
var d = new Date();
d.setUTCFullYear(yr, mo, da);
// Check that date values are valid
if (d.getUTCFullYear() != yr || d.getUTCDate() != da) {
return invalidDate;
}
// If there's an offset, apply it to minutes to get a UTC time value
min = hasOffset? +min + offSign * (offHr * 60 + offMin) : min;
// Set UTC time values of d
d.setUTCHours(hr, min, sec, ms);
return d;
}
It can be reduced to less than half that, but it's written to be easy to read and maintain.

Related

how to convert date to 20160422060933.0Z format?

In angular I have to save data to database in this time format 20160422060933.0Z ?
Someone told me that this is Microsoft time format. I don't know how to convert date to this format, anyone encountered this before?
2016 is a year, 04 is a month, and 22 is a date but i don't know what 060933.0Z is. We use Dreamfactory API and SQL Server
Later edit: based on another answer, actually this seems to be a standard format colloquially called a "LDAP date". See Converting a ldap date for some details on the format (and how to parse it in Java). It can for sure be easily parsed with any typical JS date library or even without any library.
Let's break it down into pieces.
2016 = full year
04 = month, padded to 2 digits
22 = day of month, likely also padded to 2 digits
06 = hour of day, padded to 2 digits, likely on a 24h scale
09 = minute of the hour, padded to 2 digits
33 = second of the minute, likely padded to 2 digits
. = literal
0 = probably "second fraction"
Z = offset from UTC. Z meaning UTC.
Parsing it
You have several options to parse it:
If you assume you're going to always get an UTC datetime from the backend, you can naively parse it in JavaScript just by extracting the relevant substrings.
const input = '20160422060933.0Z';
new Date(Date.UTC(
input.substr(0, 4), // year
input.substr(4, 2) - 1, // month is 0-indexed
input.substr(6, 2), // day
input.substr(8, 2), // hour
input.substr(10, 2), // minute
input.substr(12, 2), // second
("0." + input.split(/[.Z]/gi)[1]) * 1000 // ms
));
// Fri Apr 22 2016 09:09:33 GMT+0300 (Eastern European Summer Time)
You can be a little creative and actually manipulate the string into an ISO format. Then you can just use the native Date.parse function, which supports parsing ISO strings (other formats are browser-dependent). The advantage is that it'll support dates that are not UTC as well.
new Date(Date.parse(
input.substr(0, 4) + "-" + // year, followed by minus
input.substr(4, 2) + "-" + // month, followed by minus
input.substr(6, 2) + "T" + // day, followed by minus
input.substr(8, 2) + ":" + // hour, followed by color
input.substr(10, 2) + ":" + // minute, followed by color
input.substr(12, 2) + // second
input.substr(14) // the rest of the string, which would include the fraction and offset.
))
// Fri Apr 22 2016 09:09:33 GMT+0300 (Eastern European Summer Time)
Use a library like luxon, momentjs, etc. This you might already have a JS library in your project. You'd need to build a date format pattern to parse this format into a native Date object or some other library-specific object. For example, with momentjs you'd do:
moment("20160422060933.0Z", "YYYYMMDDHHmmss.SZ")
// Fri Apr 22 2016 09:09:33 GMT+0300 (Eastern European Summer Time)
Formatting into it
This side of the operation is even simpler.
Without any date library, you just need to get rid of the "-", ":" and "T" separators from the ISO format. So you can just do the following:
new Date().toISOString().replace(/[:T-]/g, "")
// '20230209175305.421Z'
If you want to use a date library, then you just do the reverse, format operation using the same pattern as for parsing. Eg. in momentjs:
moment(new Date()).utc().format("YYYYMMDDHHmmss.S[Z]")
// "20230209175222.5Z"
(note that I needed to place the "Z" in brackets due to https://github.com/moment/moment-timezone/issues/213).
Just a side note to the other answer here:
You can use ldap2date npm package for parsing, should be not that "heavy" as moment.
Code:
import ldap2date from "ldap2date";
// or import { parse, toGeneralizedTime } from "ldap2date";
const dateString = "20160422060933.0Z";
const date = ldap2date.parse(dateString);
console.log(date.toUTCString());
// Fri, 22 Apr 2016 06:09:33 GMT
const str = ldap2date.toGeneralizedTime(date);
console.log(str);
// 20160422060933Z (note: no period.)
console.log(str.replace("Z", ".0Z"));
// 20160422060933.0Z
function getLdapString(date) {
return ldap2date.toGeneralizedTime(date);
}
const d = new Date();
console.log(getLdapString(d), d.toISOString());
// 20230209181603.965Z 2023-02-09T18:16:03.965Z
And some monkey-patching to match "format":
function getLdapString(date) {
return date.getMilliseconds() !== 0
? ldap2date.toGeneralizedTime(date)
: ldap2date.toGeneralizedTime(date).replace("Z", ".0Z");
}
const d = new Date();
d.setMilliseconds(15);
const d1 = new Date();
d1.setMilliseconds(0);
console.log("Date with milliseconds: ", d.toUTCString(), getLdapString(d));
console.log("Date without milliseconds: ", d1.toUTCString(), getLdapString(d1));
// Date with milliseconds: Thu, 09 Feb 2023 18:22:27 GMT 20230209182227.15Z
// Date without milliseconds: Thu, 09 Feb 2023 18:22:27 GMT 20230209182227.0Z
Or to ignore milliseconds part completelly
function getLdapString(date) {
const copy = new Date(date);
copy.setMilliseconds(0);
return ldap2date.toGeneralizedTime(copy).replace("Z", ".0Z");
}
console.log("Date with milliseconds: ", d.toUTCString(), getLdapString(d));
console.log("Date without milliseconds: ", d1.toUTCString(), getLdapString(d1));
// Date with milliseconds: Thu, 09 Feb 2023 18:29:50 GMT 20230209182950.0Z
// Date without milliseconds: Thu, 09 Feb 2023 18:29:50 GMT 20230209182950.0Z

How to reposition datetime into the current timezone when converting an ISO 8601 datetime string to a **Date** object?

Let's say we're in London at midnight on 2020-01-01 and make an entry into an app that stores the datetime as an ISO-8601 string like this.
2020-01-01T00:00:00-00:00
Later, I am in Los Angeles and want to view this date on a chart that requires a javascript date object.
Getting the localized date object is easy.
const iso8601Date = '2020-01-01T00:00:00+00:00';
const theDate = new Date(iso8601Date);
console.log(typeOf(theDate)); // date
console.log(theDate); // Tue Dec 31 2019 16:00:00 GMT-0800 (PST)
But, sometimes we want to "ignore" the timezone offset and analyze the data as if it happened in the current timezone.
This is the result I'm looking for but don't know how to accomplish.
const iso8601Date = '2020-01-01T00:00:00+00:00';
const theRepositionedDate = someMagic(iso8601Date);
console.log(typeOf(theRepositionedDate)); // date
console.log(theRepositionedDate); // Wed Jan 01 2020 00:00:00 GMT-0800 (PST)
How do you reposition the date and return a date object?
/* Helper function
Returns the object type
https://stackoverflow.com/a/28475133/25197
typeOf(); //undefined
typeOf(null); //null
typeOf(NaN); //number
typeOf(5); //number
typeOf({}); //object
typeOf([]); //array
typeOf(''); //string
typeOf(function () {}); //function
typeOf(/a/) //regexp
typeOf(new Date()) //date
*/
function typeOf(obj) {
return {}.toString
.call(obj)
.split(' ')[1]
.slice(0, -1)
.toLowerCase();
}
This is really a duplicate of Why does Date.parse give incorrect results?, but that may not seem apparent at first glance.
The first rule of parsing timestamps is "do not use the built–in parser", even for the 2 or 3 formats supported by ECMA-262.
To reliably parse a timestamp, you must know the format. Built–in parsers try and work it out, so there are differences between them that may well produce unexpected results. It just happens that '2020-01-01T00:00:00+00:00' is probably the only supported format that is actually reliably parsed. But it does differ slightly from strict ISO 8601, and different browsers differ in how strictly they apply the ECMAScript parsing rules so again, very easy to get wrong.
You can convert it to a "local" timestamp by just trimming the offset information, i.e. '2020-01-01T00:00:00', however Safari at least gets it wrong and treats it as UTC anyway. ECMAScrip itself is inconsistent with ISO 8601 by treating date–only forms of ISO 8601 as UTC (i.e. '2020-01-01' as UTC when ISO 8601 says to treat it as local).
So just write your own parser or use a library, there are plenty to choose from. If you're only looking for parsing and formatting, there are some that are less than 2k minified (and there are examples on SO).
Writing your own is not that challenging if you just want to support straight forward ISO 8601 like formats, e.g.
// Parse ISO 8601 timestamps in YYYY-MM-DDTHH:mm:ss±HH:mm format
// Optional "T" date time separator and
// Optional ":" offset hour minute separator
function parseIso(s, local) {
let offset = (s.match(/[+-]\d\d:?\d\d$/) || [])[0];
let b = s.split(/\D/g);
// By default create a "local" date
let d = new Date(
b[0],
b[1]-1,
b[2] || 1,
b[3] || 0,
b[4] || 0,
b[5] || 0
);
// Use offset if present and not told to ignore it
if (offset && !local){
let sign = /^\+/.test(offset)? 1 : -1;
let [h, m] = offset.match(/\d\d/g);
d.setMinutes(d.getMinutes() - sign * (h*60 + m*1) - d.getTimezoneOffset());
}
return d;
}
// Samples
['2020-01-01T00:00:00+00:00', // UTC, ISO 8601 standard
'2020-01-01 00:00:00+05:30', // IST, missing T
'2020-01-01T00:00:00-0400', // US EST, missing T and :
'2020-01-01 00:00:00', // No timezone, local always
'2020-01-01' // Date-only as local (differs from ECMA-262)
].forEach(s => {
console.log(s);
console.log('Using offset\n' + parseIso(s).toString());
console.log('Ignoring offset\n' + parseIso(s, true).toString());
});
Building off of #RobG's answer I was able to speed this one up a little by using a single regex. Posting here for posterity.
const isoToDate = (iso8601, ignoreTimezone = false) => {
// Differences from default `new Date()` are...
// - Returns a local datetime for all without-timezone inputs, including date-only strings.
// - ignoreTimezone processes datetimes-with-timezones as if they are without-timezones.
// - Accurate across all mobile browsers. https://stackoverflow.com/a/61242262/25197
const dateTimeParts = iso8601.match(
/(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2}):(\d{2})(?:\.(\d{0,7}))?(?:([+-])(\d{2}):(\d{2}))?)?/,
);
// Create a "localized" Date by always specifying a time. If you create a date without specifying
// time a date set at midnight in UTC Zulu is returned. https://www.diigo.com/0hc3eb
const date = new Date(
dateTimeParts[1], // year
dateTimeParts[2] - 1, // month (0-indexed)
dateTimeParts[3] || 1, // day
dateTimeParts[4] || 0, // hours
dateTimeParts[5] || 0, // minutes
dateTimeParts[6] || 0, // seconds
dateTimeParts[7] || 0, // milliseconds
);
const sign = dateTimeParts[8];
if (sign && ignoreTimezone === false) {
const direction = sign === '+' ? 1 : -1;
const hoursOffset = dateTimeParts[9] || 0;
const minutesOffset = dateTimeParts[10] || 0;
const offset = direction * (hoursOffset * 60 + minutesOffset * 1);
date.setMinutes(date.getMinutes() - offset - date.getTimezoneOffset());
}
return date;
};
The key difference is a single regex that returns all the matching groups at once.
Here's a regex101 with some examples of it matching/grouping.
It's about double the speed of the #RobG's awesome accepted answer and 4-6x faster than moment.js and date-fns packages. 👍
const createDate = (isoDate) => {
isoDate = new Date(isoDate)
return new Date(Date.UTC(
isoDate.getUTCFullYear(),
isoDate.getUTCMonth(),
isoDate.getUTCDate(),
isoDate.getUTCMinutes(),
isoDate.getUTCSeconds(),
isoDate.getUTCMilliseconds()
));
}
const iso8601Date = '2020-01-01T00:00:00+00:00';
const theRepositionedDate = createDate(iso8601Date);
console.log(theRepositionedDate instanceof Date); // true
console.log(theRepositionedDate);
But, sometimes we want to "ignore" the timezone offset and analyze the data as if it happened in the current timezone.
Ok, then ignore it.
const iso8601Date = '2020-01-01T00:00:00+00:00';
const theDate = new Date(iso8601Date.substring(0, 19));
This works because you're creating a Date object from 2020-01-01T00:00:00 - an ISO 8601 date-time without offset.
ECMAScript section 20.3.1.15 - Date Time String Format says:
When the time zone offset is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time.

Javascript Date parsing returning strange results in Chrome

I observed some strange Date behaviour in Chrome (Version 74.0.3729.131 (Official Build) (64-bit)).
Following javascript was executed in the Chrome Dev Console:
new Date('1894-01-01T00:00:00+01:00')
// result: Mon Jan 01 1894 00:00:00 GMT+0100 (Central European Standard Time)
new Date('1893-01-01T00:00:00+01:00')
// result: Sat Dec 31 1892 23:53:28 GMT+0053 (Central European Standard Time)
I have already read about non standard date parsing via the Date ctor in different browsers, although providing valid ISO8601 values.
But this is more than strange o_o
In Firefox (Quantum 66.0.3 (64-Bit)) the same calls result in expected Date objects:
new Date('1894-01-01T00:00:00+01:00')
// result: > Date 1892-12-31T23:00:00.000Z
new Date('1893-01-01T00:00:00+01:00')
// result: > Date 1893-12-31T23:00:00.000Z
Is this a bug in Chrome?
My input is valid ISO8601 i guess?
The most important question is, how do I fix this? (hopefully without parsing the input string myself)
Okay, seems like this behaviour cannot be avoided, so you should parse dates manually. But the way to parse it is pretty simple.
If we are parsing date in ISO 8601 format, the mask of date string looks like this:
<yyyy>-<mm>-<dd>T<hh>:<mm>:<ss>(.<ms>)?(Z|(+|-)<hh>:<mm>)?
1. Getting date and time separately
The T in string separates date from time. So, we can just split ISO string by T
var isoString = `2019-05-09T13:26:10.979Z`
var [dateString, timeString] = isoString.split("T")
2. Extracting date parameters from date string
So, we have dateString == "2019-05-09". This is pretty simple now to get this parameters separately
var [year, month, date] = dateString.split("-").map(Number)
3. Handling time string
With time string we should make more complex actions due to its variability.
We have timeString == "13:26:10Z"
Also it's possible timeString == "13:26:10" and timeString == "13:26:10+01:00
var clearTimeString = timeString.split(/[Z+-]/)[0]
var [hours, minutes, seconds] = clearTimeString.split(":").map(Number)
var offset = 0 // we will store offset in minutes, but in negation of native JS Date getTimezoneOffset
if (timeString.includes("Z")) {
// then clearTimeString references the UTC time
offset = new Date().getTimezoneOffset() * -1
} else {
var clearOffset = timeString.split(/[+-]/)[1]
if (clearOffset) {
// then we have offset tail
var negation = timeString.includes("+") ? 1 : -1 // detecting is offset positive or negative
var [offsetHours, offsetMinutes] = clearOffset.split(":").map(Number)
offset = (offsetMinutes + offsetHours * 60) * negation
} // otherwise we do nothing because there is no offset marker
}
At this point we have our data representation in numeric format:
year, month, date, hours, minutes, seconds and offset in minutes.
4. Using ...native JS Date constructor
Yes, we cannot avoid it, because it is too cool. JS Date automatically match date for all negative and too big values. So we can just pass all parameters in raw format, and the JS Date constructor will create the right date for us automatically!
new Date(year, month - 1, date, hours, minutes + offset, seconds)
Voila! Here is fully working example.
function convertHistoricalDate(isoString) {
var [dateString, timeString] = isoString.split("T")
var [year, month, date] = dateString.split("-").map(Number)
var clearTimeString = timeString.split(/[Z+-]/)[0]
var [hours, minutes, seconds] = clearTimeString.split(":").map(Number)
var offset = 0 // we will store offset in minutes, but in negation of native JS Date getTimezoneOffset
if (timeString.includes("Z")) {
// then clearTimeString references the UTC time
offset = new Date().getTimezoneOffset() * -1
} else {
var clearOffset = timeString.split(/[+-]/)[1]
if (clearOffset) {
// then we have offset tail
var negation = timeString.includes("+") ? 1 : -1 // detecting is offset positive or negative
var [offsetHours, offsetMinutes] = clearOffset.split(":").map(Number)
offset = (offsetMinutes + offsetHours * 60) * negation
} // otherwise we do nothing because there is no offset marker
}
return new Date(year, month - 1, date, hours, minutes + offset, seconds)
}
var testDate1 = convertHistoricalDate("1894-01-01T00:00:00+01:00")
var testDate2 = convertHistoricalDate("1893-01-01T00:00:00+01:00")
var testDate3 = convertHistoricalDate("1894-01-01T00:00:00-01:00")
var testDate4 = convertHistoricalDate("1893-01-01T00:00:00-01:00")
console.log(testDate1.toLocaleDateString(), testDate1.toLocaleTimeString())
console.log(testDate2.toLocaleDateString(), testDate2.toLocaleTimeString())
console.log(testDate3.toLocaleDateString(), testDate3.toLocaleTimeString())
console.log(testDate4.toLocaleDateString(), testDate4.toLocaleTimeString())
Note
In this case we are getting Date instance with all its own values (like .getHours()) being normalized, including timezone offset. The testDate1.toISOString will still return weird result. But if you are working with this date, it will probably 100% fit your needings.
Hope that helped :)
This might be the case when all browsers follow their own standards for encoding date formats (but I am not sure on this part). Anyways a simple fix for this is to apply the toISOString method.
const today = new Date();
console.log(today.toISOString());

JSON.stringify(objExtraParam) giving wrong date

I'm having a javascript object as below.
var obj = { pageSize:"25",asOfDate:"Thu Sep 25 00:00:00 UTC+0530 2014"};
when i stringify it,
var d = JSON.stringify(obj);
its giving me result as
{"pageSize":"25","asOfDate":"2014-09-24T18:30:00Z"}
what could be the reason that its giving date 2014-09-24 than 2014-09-25 ?
EDIT:
My deployment server is located in US (Eastern Time UTC -5:00).when i check the site from my local machine in india its giving me date as 24 Sept 2014
UTC+0530 declares a UTC time offset. Seems that 5:30 is around the India or Sri Lanka area.
"2014-09-24T18:30:00Z" is the same as "Thu Sep 25 00:00:00 UTC+0530 2014" in two different formats. The Z in the first format is resolving to UTC (GMT) time, which in this case is -5:30. So 18:30 is 24:00 - 5:30.
So, if you are stringify-ing in a timezone that is negative offset (say in the United States UTC−08:00) then it could push the date back by one day when parsing.
I think this is what you are seeing.
Related SO Question: JSON Stringify changes time of date because of UTC
Try this
var obj = { pageSize:"25",asOfDate:"Thu Sep 25 00:00:00 UTC+0530 2014"};
obj.asOfDate = reverseUTC(obj.asOfDate);
var d = JSON.stringify(obj);
function reverseUTC(updatedDate) {
if ($.isEmptyObject(updatedDate)) {
var offset = updatedDate.getTimezoneOffset();
var currentDateTime = new Date();
updatedDate.setHours((currentDateTime.getHours() * 60 + currentDateTime.getMinutes() - offset) / 60);
updatedDate.setMinutes((currentDateTime.getHours() * 60 + currentDateTime.getMinutes() - offset) % 60);
return updatedDate;
}
}
There is no standard format for passing dates in JSON, so JSON.stringify is just calling the default date.prototype.toString() method and that is taking the timezone into account.
You need to ensure that the date is converted into a string to your particular requirements and only convert to JSON format.

Regarding JavaScript new Date() and Date.parse()

var exampleDate='23-12-2010 23:12:00';
I want to convert above string into a date and have tried a couple things:
var date = new Date(exampleDate); //returns invalid Date
var date1 = Date.parse(exampleDate); //returns NAN
This code is running fine in IE and Opera, but date is returning me an invalid Date and date1 is returning NAN in Firefox. What should I do?
The string in your example is not in any of the standard formats recognized by browsers. The ECMAScript specification requires browsers to be able to parse only one standard format:
The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ
This format includes date-only forms:
YYYY
YYYY-MM
YYYY-MM-DD
It also includes time-only forms with an optional time zone offset appended:
THH:mm
THH:mm:ss
THH:mm:ss.sss
Also included are “date-times” which may be any combination of the above.
If the String does not conform to that format the function may fall back to any
implementation-specific heuristics or implementation-specific date formats. Unrecognizable Strings or dates
containing illegal element values in the format String shall cause Date.parse to return NaN.
So in your example, using 2010-12-23T23:12:00 is the only string guaranteed to work. In practice, most browsers also allow dates of the format DD Month YYYY or Month DD, YYYY, so strings like 23 Dec 2010 and Dec 23, 2010 could also work.
Above format is only supported in IE and Chrome.
so try with another formats. following are some formats and there supporting browsers.
<script type="text/javascript">
//var dateString = "03/20/2008"; // mm/dd/yyyy [IE, FF]
var dateString = "2008/03/20"; // yyyy/mm/dd [IE, FF]
// var dateString = "03-20-2008"; // mm-dd-yyyy [IE, Chrome]
// var dateString = "March 20, 2008"; // mmmm dd, yyyy [IE, FF]
// var dateString = "Mar 20, 2008"; // mmm dd, yyyy [IE, FF]
// Initalize the Date object by passing the date string variable
var myDate = new Date(dateString);
alert(myDate);
</script>
You could parse it manually with a regular expression then call the date constructor with the date elements, as such:
var parseDate = function(s) {
var re = /^(\d\d)-(\d\d)-(\d{4}) (\d\d):(\d\d):(\d\d)$/;
var m = re.exec(s);
return m ? new Date(m[3], m[2]-1, m[1], m[4], m[5], m[6]) : null;
};
var dateStr = '23-12-2010 23:12:00';
parseDate(dateStr).toString(); //=> Thu Dec 23 2010 23:12:00 GMT-0800
JavaScript should support conversion at least from the following dateStrings:
* yyyy/MM/dd
* MM/dd/yyyy
* MMMM dd, yyyy
* MMM dd, yyyy
Try with:
var exampleDate='12/23/2010 23:12:00';
var date = new Date(exampleDate);
Use datejs and this code:
var exampleDate='23-12-2010 23:12:00';
var myDate = Date.parseExact(exampleDate, 'dd-MM-yyyy hh:mm:ss');
myDate should be a correctly constructed Date object.
Just use in this format:
var exampleDate='2010-12-23 23:12:00';
#casablanca has a good answer but it's been 10+ years and this still has a lot of weight in Google so I thought I'd update with a new answer.
TL;DR
// Use an ISO or Unix time string to generate `Month DD, YYYY`
const newDate = new Date('23-12-2010')
const simpleDate = `${newDate.toLocaleString('en-us', { month: 'long' } )} ${newDate.getDate()}, ${newDate.getFullYear()}`
// yields: December, 23 2010 (if you want date suffix, read until the end)
Background: Dates come in a lot of formats, but you're mostly going to receive:
An ISO 8601 format date (YYYY-MM-DDTHH:mm:ss.sssZ) where Z is a UTC timezone offset. You might also get a subset of this (ie, YYYY-MM-DD)
Unix timestamp format date (1539734400), where the number is literally the total amount of milliseconds since the beginning of Unix time, Jan 1st 1970.
Basics: JS has a built-in Date prototype that accepts ISO 8601 and derivatives (of just time or just date). You can instantiate with new Date and return a date object OR you can use the Date.parse() method to return a Unix timestamp.
const dateObj = new Date('23-12-2010:23:12:00') // returns date object
const dateDateOnly = new Date('23-12-2010') // returns date object
const dateTimeOnly = new Date('23:12:00') // returns date object
const dateString = Date.parse('23-12-2010:23:12:00') // returns Unix timestamp string
You can also break the date into 7 parameters: the year, the month (starting from 0), the day, the hour, the minutes, seconds and milliseconds with the time zone offset - NOTE, I've used the multi-params approach only once in my career. Since I'm in Texas I get, UTC-5 (Central Time) when I run the following:
const dateByParam = new Date(2021, 2, 26, 13, 50, 13, 30) // Fri Mar 26 2021 13:50:13 GMT-0500 (Central Daylight Time)
New-ish Stuff toLocaleString: Typically, the return from the Date object is still pretty dense like our last example (Fri Mar 26 2021 13:50:13 GMT-0500 (Central Daylight Time) so additional methods have been added to help developers.
Typically with a date, I want something like March 21st, 2021 - the day and year have been easy to get for a long time:
// Assuming myDate is a JS Date object...
myDate.getDate() // date on the calendar, ie 22
myDate.getDay() // day of the week, where 0 means Sunday, 1 means monday, etc
myDate.getFullYear() // 4 digit year, ie, 2021
But I've always had to build a function to turn getDay into January, February, March, not anymore. toLocaleString() gives you some new superpowers. You can pass it two params, a string for region (ie, en-us) and an object with what you want back (ie, { month: 'long' }). This helps internationalize the response, if need be.
// Again, assuming myDate is a JS Date object...
myDate.toLocaleString('en-us', { month: 'long' } ) // March
Date Suffix I've still seen no built-in way to get the suffix for a date, like th, st, so I built this utility function that uses the modulus % operator to check the divisor of each day number and apply the right suffix (aimed at an American audience but might be the same elsewhere?).
/**
* setDateSuffix()
*
* Desc: Takes two digit date, adds 'st', 'nd', 'rd', etc
*
* #param { integer } num - a number date
*/
export const setDateSuffix = (num) => {
const j = num % 10,
k = num % 100
if (j === 1 && k !== 11) {
return num + "st";
}
if (j === 2 && k !== 12) {
return num + "nd";
}
if (j === 3 && k !== 13) {
return num + "rd";
}
return num + "th";
}
Altogether now.. Long winded way of getting here, but if I am given an ISO or Unix date and I want Month DDth, YYYY, this is what I run:
// setDateSuffix IS NOT PART OF BUILT-IN JS!
const newDate = new Date('23-12-2010')
const simpleDate = `${newDate.toLocaleString('en-us', { month: 'long' } )} ${setDateSuffix(newDate.getDate())}, ${newDate.getFullYear()}`
// yields: December 23rd, 2010
Note - all of this will likely change, hopefully for the better, when temporal becomes a reality in JS: https://github.com/tc39/proposal-temporal. Look forward to somebody's 2030 update of this post!

Categories

Resources