I'd like to check whether a string does represent a Date with an given format.
I tried Date.parse(string, format) but it parses the string to date even if it's in a whole different format. E.g.:
Date.parse("2015-07-04T23:10:00.000+02:00", "yyyy-MM-ddTHH:mm:ss.SSSZ") // Parsed as a date
Date.parse("2000", "yyyy-MM-ddTHH:mm:ss.SSSZ") // Parsed as a date also`
I don't want to parse the second row as a date, because its not in the required format.
I also tried Date.parseExact() method of Date.js but it didn't parsed the date if I provided a timezone and a format like above.
The right solution was based on RobG's comment: (but thanks to everyone for helping me)
moment("2015-07-04T23:10:00.000+02:00", "yyyy-MM-ddTHH:mm:ss.SSSZ", true).isValid()
Every other solution succeeded the parsing even if the input was only a year which I tried to avoid. The last parameter "true" stands for the "strict" parsing which provides exactly the output that I was looking for.
You can leverage MomentJS and its function .format()
How does it work? here is the documentation, it's fairly simple, you wanna use your string in combination with the format string.
MomentJS .format()
And here is the quick demo Fiddle:
var myString = "2015-07-04T23:10:00.000+02:00";
var formatString = "yyyy-MM-ddTHH:mm:ss.SSSZ";
if (moment(myString, formatString)._i == myString) console.log("GOOD");
1-liner with momentJS
I basically format your string in targeted format then check if the result matches your string.
Worth noting is that MomentJS is (IMHO) the best date and time lib for JS. I never found a reason to venture beyond it since I discovered it, after using some of the less capable libs in the past.
If you don't wanna use lib, making a regex to suit your needs is a viable alternative of similar length.
Altho, if you intend to work with a lot of dates/times, MomentJS is still a way to go as it offers so many useful things which cannot be done by regexes alone.
Why not use regular expression to check if input matches the format and parse it if it does?
reg=new RegExp(/[0-9]{4}\-[0-9]{2}\-[0-9]{2}T[0-9]{2}\:[0-9]{2}\:[0-9]{2}\.[0-9]{3}\+[0-9]{2}\:[0-9]{2}/);
str="2015-07-04T23:10:00.000+02:00";
date=new Date(str);
if(str.match(reg) && date.toString()!='Invalid Date')
{
Date.parse(str);
}
Edited to add date check.
Related
Similar questions has been asked many times but I couldn't find a more concrete solution. The things I'm doing are:
I have a <input type="date"> inside my HTML which when clicked opens a calender with date in dd/mm/yyyy format.
I change the html5 date to timestamp to send to my db by Date.parse(html5Date) and in the server I modify the date and send it back to my Angular app.
I now convert the timestamp back to Date object by new Date(timestamp).To print the date in a human-friendly format inside a table I do [date.getDate(), date.getMonth() + 1, date.getFullYear()].join('/').
On edit (PUT request), I again capture the date from HTML, convert it to timestamp, send it to server and process the returning date back to html date.
Other than these, I also do a ton of functionalities like date comparison, adding hours to the dates, show time of the day etc inside the HTML:
Just these simple operations are over 120 lines of code which I think is ridiculous and error prone. I've looked into Angular Datepicker but it's a bit confusing. Also sometimes the HTML date is of type Object and sometimes it's String so Date.parse() gives error.
Are there any developer friendly methods that does : copy HTML5 date (from datepicker) --> change to timestamp (for angular&server) --> format timestamp back to string/object (for html)? Thank You :)
Note: Angular throws a lot of annoying error in console saying dateformat is wrong (being html date type) but doesn't stop code from running
Sounds like you are doing waaay to many conversions. I would argue that there should only be one way dates are represented: as Date objects in the programming language. There are only a few conversions that need to happen:
Date <=> Integer milliseconds since the epoch to pass to server
Date <=> String human-readable format to display to user
Any thing beyond this is asking for trouble. Comparisons can be made by casting to int date.getTime(), comparing, and casting back to Date. Ditto for additions. Note that Date.parse is implementation dependent in what it will accept, although all of them will accept ISO 8601 formatted date strings anything else is guesswork. Which means you will have to deal with converting strings by hand, something like the following:
var toDate = str => {
var splitter = str.indexOf("/") === -1 ? "-" : "/";
var [mon, day, year] = str.split(splitter);
return new Date(year, mon - 1, day);
};
var toDateString = date => {
return "" + date.getFullYear() + (date.getMonth() + 1) +...
};
Note that there's no validation, that's left as an exercise to the reader.
A WORD ABOUT MOMENT.JS
moment.js is awesome. Its also huge, its a kitchen-sink API with a heft to match. You're already loading angular, so think carefully before bulking the size of your payload with another huge library.
Moment.js is a powerful date formatting and manipulation library. A lot of things you can do in Moment.js are a single line of code, which makes life a lot easier. I agree, without using a library like this date formatting and handling can be a pain.
http://momentjs.com/
EDIT: fyi, I use this with my Angular app and find it extremely useful!
Given a datestring, how can I get the format string describing that datestring?
Put another way, how can I get the format string that Date() or MomentJS (might be different for each, that's fine) would use to parse that datestring if one didn't pass an explicit format to use?
So given '2016-01-01' it should output something like 'YYYY-MM-DD', for example.
(I am aware this is a simple question and may have an answer somewhere, but it is difficult to word concisely, so I could only find questions and answers about how to parse datestrings or how to display dates. None about how to output the format itself.)
Consolidating information from Matt Johnson's answer, some comments, and my own contribution.
With Moment.js (version 2.10.7+), you can use the Creation Data API. Something like this in Node.js:
moment('2016-01-01 00:00:00').creationData().format
outputs
'YYYY-MM-DD HH:mm:ss'
Just as any date parsing is, there is ambiguity about the format of many datestrings due to things such as locale (the order of months and days are switched between the US and Europe, for example). But the above method is sufficient for me.
You can't, without having additional information, such as the locale. For example, 01/12/16 could be Jan 12, 2016, December 1, 2016, or December 16, 2001.
Even when you know the locale, there are several places in the real world where more than one date format is used, depending on context.
See https://en.wikipedia.org/wiki/Date_format_by_country
However, if you are just trying to determine which one of multiple known formats was used to parse the input string, moment has an API for that called Creation Data. For example:
var m = moment("2016/06/10", ["YYYY-MM-DD", "MM/DD/YYYY"], true);
var f = m.creationData().format; // "MM/DD/YYYY"
I'm trying to loop through an array and work out which items are dates. To do this I am running the values through Date.parse(value), which is supposed to only parse valid dates.
The problem is that this string is parsed as a date
"Test Title 1"
Example: http://jsfiddle.net/jonhobbs/LHeQ8/
This tells me that you can't trust Date.parse at all but I don't know of an alternatve. I've tried the moment.js library and that gives me the same thing as it uses Date.parse() internally.
Answer was to use a regex instead.
I found a very useful regular expression for testing format and content of a date field in a regex example site
BUT I get a validation when I put in dates older than 2000 and since this is a field for inputting date of birth you can see why it would be a problem. I am sure it is an easy fix but regular expressions intimidate me.
$('#txtDOB').blur(function() {
//$('span.error-keyup-5').remove();
var inputVal = $(this).val();
var dateReg = /^[0,1]?\d{1}\/(([0-2]?\d{1})|([3][0,1]{1}))\/(([1]{1}[9]{1}[9]{1}\d{1})|([2-9]{1}\d{3}))$/;
if(!dateReg.test(inputVal)) {
alert('invalid date format: ' + inputVal);
}
I am not married to this solution so if you can suggest a better way please comment away.
Instead of testing if a string matches one or more formats that you think might be good dates, I would suggest instead asking JavaScript if it thinks it is a valid date:
function isValidDate(str){
return !isNaN(new Date(str));
}
This assumes that you're going to accept what the user gives you in any of a variety of formats (e.g. the horrid US MM/DD/YYYY or the more sane ISO8601 YYYY-MM-DD). If instead you have a specific format you will only accept, then parse your string based on that, pull out the year/month/date, and then ask JavaScript if this is a valid date:
function isValidDate(year, month, date) {
var d = new Date(year*=1, month-=1, date*=1, 12); // noon to skip DST issues
return d.getFullYear()==year && d.getMonth()==month; // wrong date->wrong month
}
You need to check that the year/month/date all match because new Date(2011,11,32) is accepted and interpreted as 2012-1-1.
See also: Javascript method to ensure that a date is valid
There's a whole lot of mess there. First, eliminate all the {1}'s. That just means one instance, which is totally redundant. Also, a character class with one value is the same as the character itself. So, [1] becomes 1.
So, that leaves us with:
/^[01]?\d\/(([0-2]?\d)|([3][01]))\/((199\d)|([2-9]\d{3}))$/
This is MM/DD/YYYY presumably. but the YYYY is just 199[0-9] and any year > 2000 and < 9999. Wow, that's a date range!
As a basic, try:
/^[01]?\d\/(([0-2]?\d)|([3][01]))\/([12]\d{3}))$/
This gives a year range of 1000 - 2999. But as Tim said above, if you want really valid dates, you should use a specific date validator.
If you need to parse date strings into dates then I would check out this library:
DateJS
I am currently having some issues converting a string dateTime object in JavaScript
I am assuming it is because my string cannot me used properly in a new Date() but I'm not sure that is the problem.
My Input: "2011-09-29 14:58:12"
My code:
var date = "2011-09-29 14:58:12";
var added = new Date(date);
var year = added.getYear();
However, my year var contains NaN. Same with getDay() or getMonth(). What is the problem?
ps: I'm getting the date in it's format from a SQLite database. And I'm using Titanium Mobile, so javascript and SQLite are the only things involved
You're relying on the Date constructor parsing an unsupported format. Until recently, there was no standard string format supported by the Date constructor. As of ECMAScript5, there is one (YYYY-MM-DDTHH:MM:SS, note the T rather than space), but it's only been specified for just under two years and naturally doesn't work in older browsers.
For the time being, your best bet is to parse it yourself (you can find code in this question and its answers), or use something like DateJS, MomentJS, date-fns, etc. to parse it for you.
The Date constructor will not parse a string for you. You'll need to use Date.parse to do that. Interestingly enough, Date.parse doesn't actually return a Date. Instead it returns a unix timestamp. You can then pass the unix timestamp into the Date constructor to get what you're looking for.
var d = new Date(Date.parse("2011-09-29 14:58:12"));