How to validate timestamp in javascript - javascript

How do you validate timestamp using javascript and timestamp to accept multiple formats
e.g. YYYY-MM-DD HH:mm:ss.S, YYYY-MM-DD HH:mm:ss AM/PM.

You can validate if a string is a valid timestamp like this:
var valid = (new Date(timestamp)).getTime() > 0;
var valid = (new Date('2012-08-09')).getTime() > 0; // true
var valid = (new Date('abc')).getTime() > 0; // false
Revisiting this answer after many years, validating dates can still be challenging. However, some of the argument is that the built in parser accepts a number of input format, many of which have little relevance.
The question here is to validate a timestamp of multiple formats, and unless the date parser can help you, there is a need to convert the timestamp into a generic format that is comparable. How to convert into this format depends on the format of the input, and in case of incompatible inputs, a tailored conversion algorithm will have to be developed.
Either use the built in date parser, as described above, otherwise, you will have to parse the input manually, and validate it accordingly.

The solution of #Jørgen is nice but if you have a date before January 1, 1970 your timestamp will be a negative number but also a valid timestamp.
function isValidTimestamp(_timestamp) {
const newTimestamp = new Date(_timestamp).getTime();
return isNumeric(newTimestamp);
}
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
The numeric validation I took from the following SO answer.
For example:
isValidTimestamp('12/25/1965') // true

Every valid number is a timestamp. If it satisfies the condition of valid integer number then it will also satisfy the condition of the valid timestamp.
Timestamp = The number of milliseconds since 1970/01/01

var d = Date.parse(your_timestamp);
d should be a valid number and not NaN.
ref: http://www.w3schools.com/jsref/jsref_parse.asp

You can't generically parse a date string without knowing beforehand what the format is, or at least that it is one of a limited number of formats.
If the date component is always in ISO8601 format (yyyy-mm-dd) and the time is either 24hr or 12hr with AM or PM, you should be able to easily split off the time, look for AM or PM, then treat the time as 12 or 24hr depending on whether it's present or not.
Timezones must be specified as either UTC (Z) or hours +/-UTC, abbreviations such as EST are ambiguous (and not standardised).

by using new Date().getTime(); you can do this
and doing something like this
var getDate="12-12-2012";
var myDate=getDate.split("-");
var getDate=myDate[1]+"/"+myDate[0]+"/"+myDate[2];
alert(new Date(getDate).getTime());

/**
* Determine whether string is timestamp
*
* #example
*
* isTimestamp('1606205966448'); // true
* isTimestamp(1606205966448); // true
* isTimestamp('1606205966448qwe'); // false
* isTimestamp('2020-11-24T08:19:26.448Z'); // false
*
* #param {string|number} n
* #returns {boolean}
*/
function isTimestamp(n) {
const parsed = parseFloat(n);
return !Number.isNaN(parsed) && Number.isFinite(parsed) && /^\d+\.?\d+$/.test(n);
}
export default isTimestamp;

Warning! The answer from Jørgen doesn't work before 1970.
getTime will return NaN (Not a Number) when it's not a valid date so we'll just use the built-in function isNaN to check, and inverse the value with !.
!isNaN(new Date("1969-02-13").getTime())
Working with dates can be a hassle. It's recommended to use libraries that are battle-tested. Something like date-fns or similar.

Related

Same date in all timezones

I have a problem showing the same date in all timezones.
Users input is for example 01-01-2002 and I store it like a date with Eureope/Berlin timezone
parseFromTimeZone(String(birthDate), { timeZone: 'Europe/Berlin' })
and the result of parseFromTimeZone is this string '2001-12-31T23:00:00.000Z'. String date counts with timezone in Berlin that is why it is shifted for one hour.
And I need to get from '2001-12-31T23:00:00.000Z' this 01-01-2002 in all timezones.
I using formatISO(new Date(date), { representation: 'date' })) this returns 01-01-2002 when my timezone is Europe/Prague or Europe/Berlin
but when I change the timezone to America/Tijuana then formatISO returns 2001-12-31 and that is wrong I need to have the same date as is in Europe/Berlin always! Bud for Asia/Tokyo this function returns 01-01-2002 that is right ...
Some ideas? I have tried a lot of solutions but none works for all timezones...
I am using "date-fns": "^2.15.0", "date-fns-timezone": "^0.1.4"
Try this function with an ISO_8601 date, then change the timezone in your computer's settings and try again with the new timezone. It should print the same date on your web page for both time zones.
getDateFromISO(iso_string: string): string | Date {
if (!iso_string)
return null;
const isIsoDate = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(iso_string); // check if string is in format 2022-01-01T00:00:00.000Z
const isDateTimeWithoutZone = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(iso_string); // check if string is in format 2022-01-01T00:00:00
const isDateYMD = /\d{4}-\d{2}-\d{2}/.test(iso_string); // check if string is in format 2022-01-01
if (!isIsoDate && isDateTimeWithoutZone)
iso_string += '.000Z';
else if (!isIsoDate && isDateYMD)
iso_string += 'T00:00:00.000Z';
else if (isIsoDate)
iso_string = iso_string;
else
return iso_string;
const dateFromServer = new Date(iso_string);
const localOffset = new Date().getTimezoneOffset(); // in minutes
const localOffsetMillis = 60 * 1000 * localOffset;
const localDate = new Date(dateFromServer.getTime() + localOffsetMillis);
return localDate;
}
The Date object, despite its name, is does not represent a "date". It represents a timestamp. All that it stores internally is the number of milliseconds since the Unix epoch (which is UTC based). It outputs values based on either UTC or the local time zone of the machine where its running, depending on the function being called.
Thus, if you construct a Date object from a date-only value, you're really taking "the time at midnight" from that time zone and adjusting it to UTC. This is demonstrated by your example of 2002-01-01 in Europe/Berlin. Your treating that as 2002-01-01T00:00:00.000+01:00, which indeed has a UTC equivalent of 2001-12-31T23:00:00.000Z, and thus doesn't carry the same year, month, and day elements as the intended time zone.
You really only have two options to deal with date-only values if you want to prevent them from shifting:
Your first option is to use the Date object, but treat the input as UTC and only use the UTC-based functions. For example:
var dt = new Date(Date.UTC(2002, 0, 1)); // "2002-01-01T00:00:00.000Z"
var y = dt.getUTCFullYear(); // 2002
var m = dt.getUTCMonth() + 1; // 1
var d = dt.getUTCDate(); // 1
var dtString = d.toISOString().substring(0, 10) // "2002-01-01"
If you need to parse a date string, be aware that current ECMAScript spec treats date-only values as UTC (which is what you want), but in the past such behavior was undefined. Thus some browsers might create a local-time result from new Date('2002-01-01'). You may want to explicitly add the time and Z, as in new Date('2002-01-01' + 'T00:00:00.000Z') to be on the safe side.
If you intend to use date-fns, be careful - the parseISO and formatISO functions use local time, not UTC.
The second option is to not use the Date object. Keep the dates in their string form (in ISO 8601 yyyy-mm-dd format), or keep them in a different object of either your own construction or from a library.
The ECMAScript TC39 Temporal proposal is intended to fix such deficiencies in JavaScript. In particular, the Temporal.Date object (preliminary name) will be able to be used for date-only values without having the shifting problem you and so many others have encountered. The proposal is currently in Stage 2 of the ECMAScript process, so it's not available to use today, but this problem will be solved eventually!

How to convert JavaScript Date object to string that is compatible with datetime-local input?

Basically I have a Date object. How can convert it to a string compatile with datetime-local format yyyy-MM-ddThh:mm?
I tried Date.toISOString method, but it doesn't work as it appends .SSSZ at the end. Gives me the following output The specified value "2017-04-10T17:02:00.320Z" does not conform to the required format. The format is "yyyy-MM-ddThh:mm" followed by optional ":ss" or ":ss.SSS"..
Does anyone have any clean solution to this problem?
I used moment.js library to format the date accordingly. This line of code does the trick moment(date).format("YYYY-MM-DDTkk:mm").
Either theDate.toISOString().substring(0, 16), or build the string yourself with the getFullYear, getUTCDate, getUTCMonth (remember it starts at 0), etc. methods. Or use a library to do it.
I'm running into the same problem, but I didn't want to use moment or any other big lib just for a simple calculation.
I just used the ISO date but added the timezone offset, so the input doesn't go crazy when using the arrows to navigate the date values.
const offset = new Date().getTimezoneOffset() * 1000 * 60
const getLocalDate = value => {
const offsetDate = new Date(value).valueOf() - offset
const date = new Date(offsetDate).toISOString()
return date.substring(0, 16)
}
basically it adds the timezone offset and converts that to an ISO date, but then we strip the timezone with the substring(0, 16)
this gives us the correct "timezoned ISO" date.
I'm giving it a try but so far it works okay. I wish this gets resolved natively, it is weird that it doesn't work out of the box.
use moment.js to format the date to the corresponding one:
moment(new Date()).format('YYYY-MM-DDTHH:mm')
but not: moment(date).format("YYYY-MM-DDTkk:mm")
the previous answer is wrong !!
kk is between 1 - 24 (which is not compatible with the textfield DateTime local)

Javascript method Date() is returning wrong date (Feb 9 instead of Sep 2) on my system,

I have a JavaScript method which gets current date and returns its universal time. Below is the code:
function calUTCTime(offset) {
var currentDate = new Date();
var utc = currentDate.getTime() - (currentDate.getTimezoneOffset() * 60000);
var result = new Date(utc + (3600000 * offset));
return result .toLocaleString();
}
Above code is returning wrong date, it is replacing date with month and date format in my system is dd-MM-yyyy, OS is Windows 8. I tried on other system's and the date is correct but on my system it is wrong. Please share suggestions.
That is exactly what I would expect from .toLocaleString(). The browser is determining your language (or "locale") from the OS and using it to choose how to output the string. If you want a generic human-readable date format, try a simple .toString() instead.
If you want complete and total control over how a date is formatted, try a library like moment.js. For example, your above code could be condensed to:
return moment().utc().format("YYYY-MM-DD"); // "2014-09-02"
There is another post that summarizes the differences between the two methods: JavaScript: Difference between toString() and toLocaleString() methods of Date

Validate ISO 8601 Date/Time in JavaScript [duplicate]

This question already has answers here:
Regex validate correct ISO8601 date string with time
(7 answers)
Closed 3 years ago.
I have a DateTime string ISO8601 formated
2012-10-06T04:13:00+00:00
and the following Regex which does not match this string
#(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})\+(\d{2})\:(\d{2})#
I can't figure out why it does not match.
I escaped metacharacters, for me it seems to be OK.
http://jsfiddle.net/5n5vk/2/
EDIT :
The right way: http://jsfiddle.net/5n5vk/3/
Incomplete Regex
It's incomplete as it matches invalid date such as 2013-99-99T04:13:00+00:00.
Better solution
The regex below won't match this kind of invalid date (cf. ISO 8601 Date Validation That Doesn’t Suck). You can test with the following code :
re = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/
var testDates = {
'date' : "2012-10-06T04:13:00+00:00",
'validDate' : "0785-10-10T04:13:00+00:00",
'invalidDate' : "2013-99-99T04:13:00+00:00",
'1234Date': '1234'
}
for (var d in testDates) {
if (re.test(testDates[d])) { console.info('[valid]: '+testDates[d]); }
else { console.error('[invalid]: '+testDates[d]); }
}
I found the RegExp that also tries to validate the date a bit overkill for me. I Just wanted to know if a string contains an ISO 8601 date string. I'll check if the date is actually valid after I have converted it to a Date object.
Here are 2 versions of the RegExp. This first checks if the string is a valid ISO 8601 date string. The other tests for a full date string including the hours/minutes/seconds (Commonly used in API's)
/**
* RegExp to test a string for a ISO 8601 Date spec
* YYYY
* YYYY-MM
* YYYY-MM-DD
* YYYY-MM-DDThh:mmTZD
* YYYY-MM-DDThh:mm:ssTZD
* YYYY-MM-DDThh:mm:ss.sTZD
* #see: https://www.w3.org/TR/NOTE-datetime
* #type {RegExp}
*/
var ISO_8601 = /^\d{4}(-\d\d(-\d\d(T\d\d:\d\d(:\d\d)?(\.\d+)?(([+-]\d\d:\d\d)|Z)?)?)?)?$/i
/**
* RegExp to test a string for a full ISO 8601 Date
* Does not do any sort of date validation, only checks if the string is according to the ISO 8601 spec.
* YYYY-MM-DDThh:mm:ss
* YYYY-MM-DDThh:mm:ssTZD
* YYYY-MM-DDThh:mm:ss.sTZD
* #see: https://www.w3.org/TR/NOTE-datetime
* #type {RegExp}
*/
var ISO_8601_FULL = /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(([+-]\d\d:\d\d)|Z)?$/i
// Usage:
ISO_8601_FULL.test( "2016-05-24T15:54:14.876Z" ) // true
ISO_8601_FULL.test( "2002-12-31T23:00:00+01:00" ) // true
ISO_8601_FULL.test( "2016-02-01" ) // false
ISO_8601_FULL.test( "2016" ) // false
ISO_8601.test( "2016-02-01" ) // true
ISO_8601.test( "2016" ) // true
ISO_8601.test( "2002-12-31T23:00:00+01:00" ) // true
Don't quote the regex when specifying a regex in js. Forward slash is enough.
alert($('#datepicker').val());
if($('#datepicker').val().match(
/(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})[+-](\d{2})\:(\d{2})/
)) {
alert('ok');
} else {
alert('not ok');
}​
JavaScript date.toISOString() regex
This only attempts to solve the basic pattern of 2017-06-17T00:00:00.000Z that you expect from Javascript doing it.
const isoPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
One of the most annoying things about JSON is one cannot simply pass a date through and expect it to convert properly. Since most people use JavaScript, this is probably practical.
Here's a demo snippet if you have to pass to mongo and need to convert.
if (isoPattern.test(json.startDate))
json.startDate = new Date(json.startDate);
I argue this is a better approach as you can be assured the date will parse, then you can check desired range, all being pretty straight forward and easy to maintain as regex is great but to a point.
How about only testing if you can create a Date object of the string, if that is the purpose of the test?
new Date("2016-05-24T15:54:14.876Z").toString() === 'Invalid Date' // false
new Date("Invalid date").toString() === 'Invalid Date' // true
To add to all these good answers, I found this one to be working quite good for just ISO dates (no time)
(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))
(v = pass x = does not pass)
2016-12-30 v
2016-13-31 x
2016-01-32 x
2016-02-29 v
2016-02-30 x
2017-02-29 v -> that's a false positive
1889-01-01 x -> you can add accepted centuries in the list: (?:18|19|20)
2099-01-01 v

Javascript Date(dateString) returns NaN on specific server and browser

I'm using the Javascript Date(string) constructor with a date format of "yyyy-mm-dd". The constructor works just fine in IE 9 and Firefox unless the app is running on our testing VM which is running IIS. If it's on the VM, in IE 9 it returns 'NaN', but still works normally in Firefox.
var dateAsString = "2011-11-09";
var dateCreated = new Date(dateAsString);
I was under the assumption that the server had nothing to do with client-side Javascript. Any suggestions?
And for those of us who want to know how to replace hyphens (aka dashes) with slashes:
new Date(dashToSlash(string));
That uses this function:
function dashToSlash(string){
var response = string.replace(/-/g,"/");
//The slash-g bit says: do this more than once
return response;
}
In my case it's much easier to convert hyphens to slashes selectively (only where it's needed for the Date() function) than to replace the date format everywhere in my code.
Note: you really need to define a separate 'response' variable and assign it the value of the replace operation result. If you don't, the string is returned unaltered in Chrome. That's not a huge problem, since Chrome doesn't have a problem with hyphenated date strings to begin with. But still...
Just use slashes instead of hyphens if you can.
EDIT: Expanded clarification...
The ISO 8601 standard format uses the hyphen as a date separator. My answer does not mean you do not need to follow standards. You can use slashes only for the Date constructor if necessary.
It's because of the date format. For some reason, IE and Safari get tripped up with yyyy-mm-dd. Use another date format and you should be all set.
It's talked about here:
http://biostall.com/javascript-new-date-returning-nan-in-ie-or-invalid-date-in-safari
I suggest attempting a more reliable form of date parsing. The example below uses setFullYear(). Does IE produce a different result with the code below?
/**Parses string formatted as YYYY-MM-DD to a Date object.
* If the supplied string does not match the format, an
* invalid Date (value NaN) is returned.
* #param {string} dateStringInRange format YYYY-MM-DD, with year in
* range of 0000-9999, inclusive.
* #return {Date} Date object representing the string.
*/
function parseISO8601(dateStringInRange) {
var isoExp = /^\s*(\d{4})-(\d\d)-(\d\d)\s*$/,
date = new Date(NaN), month,
parts = isoExp.exec(dateStringInRange);
if(parts) {
month = +parts[2];
date.setFullYear(parts[1], month - 1, parts[3]);
if(month != date.getMonth() + 1) {
date.setTime(NaN);
}
}
return date;
}
Source: http://jibbering.com/faq/#parseDate

Categories

Resources