Difference (in days) between two days in yyyy-mm-dd format? - javascript

Sorry if this has been asked before, but I haven't been able to find anything. Here's essentially what I'm trying to do:
new Date(response.departureDate).getTime() - new Date(response.arrivalDate).getTime()
I need to calculate the total number of days (will always be a whole integer) between an arrival and departure date. These dates are strings, structured as 'YYYY-MM-DD'.
How do I go about this?

You can use regexp OR a much simpler approach would be to become familiar with MomentJS API that lets you deal with dates in JS very smoothly (works in Node and browser)
http://momentjs.com/
It does add another tool to your toolbox, but as soon as you are manipulating dates, it is definetely worth it IMHO.
Way to go with MomentJS :
var depDate = moment(response.departureDate);
var arrDate = moment(response.arrivalDate);
var nbDays = depDate.diff(arrDate, 'days');

Look at the Miles' answer here
Just change it to:
function parseDate(str) {
var mdy = str.split('-')
return new Date(mdy[2], mdy[0]-1, mdy[1]);
}
function daydiff(first, second) {
return Math.round((second-first)/(1000*60*60*24));
}
and use:
daydiff(parseDate(response.departureDate), parseDate(response.arrivalDate));

You can use RegEx to change them.
new Date(response.departureDate.replace(/-/g, "/")).getTime()
- new Date(response.arrivalDate.replace(/-/g, "/")).getTime()
So the RegEx .replace(/-/g, "/") will replace all the - to /, and JavaScript will be able to read it right.

I hope this example help for you
Apart from .diff(), you could also use moment durations: http://momentjs.com/docs/#/durations/
Example Fiddle: https://jsfiddle.net/abhitalks/md4jte5d/
Example Snippet:
$("#btn").on('click', function(e) {
var fromDate = $('#fromDate').val(),
toDate = $('#toDate').val(),
from, to, druation;
from = moment(fromDate, 'YYYY-MM-DD'); // format in which you have the date
to = moment(toDate, 'YYYY-MM-DD'); // format in which you have the date
/* using duration */
duration = moment.duration(to.diff(from)).days(); // you may use duration
/* using diff */
//duration = to.diff(from, 'days') // alternatively you may use diff
/* show the result */
$('#result').text(duration + ' days');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.1/moment.min.js"></script>
From: <input id="fromDate" type='date' />
To: <input id="toDate" type='date' />
<button id="btn">Submit</button><hr />
<p id="result"></p>

You can use something like this
function countDays(date1, date2)
{
var one_day=1000*60*60*24;
return Math.ceil((date1.getTime()- date2.getTime()) /one_day);
}
countDays(new Date(response.departureDate), new Date(response.arrivalDate));

Related

Date conversion resulting into time zone issue

I am trying to get functionality - if the user entered date is less than the current date I need to show an error message on the screen, I implemented the following code which is working fine in my local system date but not working in other time zones. Can anyone please help in getting this.
I need to use only javascript or jquery. I was not supposed to use other libraries.
dateFormat = function(value, event) {
let newValue = value.replace(/[^0-9]/g, '').replace(/(\..*)\./g, '$1');
const dayOrMonth = (index) => index % 2 === 1 && index < 4;
// on delete key.
if (!event.data) {
return value;
}
return newValue.split('').map((v, i) => dayOrMonth(i) ? v + '/' : v).join('');
}
checkStart = function(value) {
var newDate = new Date().toISOString();
var inputDate = new Date(value).toISOString();
var today = new Date(newDate).setHours(0,0,0,0);
var userDate = new Date(inputDate).setHours(0,0,0,0);
if(userDate < today) {
$('#error-msg3').show();
$('#startDate').val('');
} else {
$('#error-msg3').hide();
}
}
<input type="tel" maxlength="10" id="startDate" name="startDate" placeholder="mm/dd/yyyy"
oninput="this.value = dateFormat(this.value, event)" onblur="checkStart(this.value)" required/>
<span id="error">Start date should not be lesser than the current date.</span>
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
Server and Db May run on a different timezone, (UTC preferred ) and when you sen date as a string it doesn't have any timezone there instead it is just a string.
Try sending it as a timestamp or UTC date string
So that server and db will automatically convert it to their timzone and store it. and when any user fetch it from other time zone it will automatically converts to their timezone (but you store string it will just be treated as a string everywhere)
let d = new Date()
console.log(d.getTime())
//or get utc string
console.log(d.toUTCString())
Send this value to your server (API)
Your code runs entirely on the client so timezone is irrelevant.
In the OP there is:
var newDate = new Date().toISOString();
...
var today = new Date(newDate).setHours(0,0,0,0);
The conversion of Date to string to Date to number is inefficient and unnecessary. The following is equivalent:
let today = new Date().setHours(0,0,0,0);
Similarly for inputDate:
var inputDate = new Date(value).toISOString();
...
var userDate = new Date(inputDate).setHours(0,0,0,0);
is equivalent to:
let userDate = new Date(value).setHours(0,0,0,0);
All calculations are local so timezone is irrelevant. Also see Why does Date.parse give incorrect results?
Attempting to control user input using script is always fraught as there are many cases that are either impossible or impractical to code around. The use of a tel input for Dates is an example. The whole issue can be avoided by using a date input and setting a min value to today. Then users can't select a date before today and your issue is solved, e.g.
window.onload = function() {
let dateEl = document.getElementById('dateInput');
dateEl.min = new Date().toLocaleString('en-CA', {year:'numeric', month:'2-digit', day:'2-digit'});
}
<input id="dateInput" type="date">
If you are comparing the date sent by the user to a date on the server, then user system clock accuracy and timezone may be an issue, but that isn't explained in the OP.
If that is an issue, then you need to ask another question on that specific topic.
If you really want to manually control the input date and show an error message when invalid dates are selected, then parse the value from the date input and compare it to the start of today and go from there:
// Parse YYYY-MM-DD as local
function parseYMDLocal(s) {
let [Y, M, D] = s.split(/\D/);
return new Date(Y, M-1, D);
}
// Check if date in YYYY-MM-DD format is before today
function isBeforeToday(d) {
return parseYMDLocal(d) < new Date().setHours(0,0,0,0);
}
function checkValue() {
let errEl = document.getElementById('errEl');
errEl.textContent = '';
console.log(typeof this.value);
if (isBeforeToday(this.value)) {
errEl.textContent = 'Date must be today or later';
} else {
// do something else
}
}
window.onload = function() {
document.getElementById('dateInp').addEventListener('blur', checkValue, false);
}
#errEl {color: red}
<input id="dateInp" type="date"><span id="errEl"></span>

Compare one date with today using DD-MM-YYYY format

I want to compare a date (mydate) with today. I tried
new Date(mydate) < new Date();
which works in all cases apart from the case my date equals today. In that case the above returns true since it compares the time included. However, I want to compare only the date, not the time.
I tried moment.js as well:
moment(mydate).format('DD-MM-YYYY')<moment().format('DD-MM-YYYY')
however, not even this one did work. What do I have to write?
You can use moment function isSame and provide the second argument as the granularity level you want for your comparison. The granularity levels can be strings like, 'year', 'month', 'day'
moment('2010-01-01').isSame('2010-02-01', 'day');
You can also look into similar functions documented over there which might help you better with your requirement.
Is Before
Is Same
Is After
Is Same or Before
Is Same or After
Is Between
All of these supports different granularity levels.
As a sidenote, to create a date in your supplied format do:
moment("25-12-1995", "DD-MM-YYYY");
You can simply do following using moment js
$(document).ready(function() {
$('.compare').click(function(e) {
var date = $('#date').val();
var now = moment().format('YYYY-MM-DD');
var then = moment(date).format('YYYY-MM-DD');
if (now > then) {
$('.result').text('Date is past');
} else if(now == then) {
$('.result').text('Date is today');
} else {
$('.result').text('Date is future');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.3/moment.min.js"></script>
<input type="text" name="date" id="date" value="2014-12-18" placeholder="yyyy-mm-dd">
<button class="compare">Compare date to current date</button>
<br>
<div class="result"></div>

Remove Seconds/ Milliseconds from Date convert to ISO String

I have a date object that I want to
remove the miliseconds/or set to 0
remove the seconds/or set to 0
Convert to ISO string
For example:
var date = new Date();
//Wed Mar 02 2016 16:54:13 GMT-0500 (EST)
var stringDate = moment(date).toISOString();
//2016-03-02T21:54:13.537Z
But what I really want in the end is
stringDate = '2016-03-02T21:54:00.000Z'
There is no need for a library, simply set the seconds and milliseconds to zero and use the built–in toISOString method:
var d = new Date();
d.setSeconds(0,0);
document.write(d.toISOString());
Note: toISOString is not supported by IE 8 and lower, there is a pollyfil on MDN.
While this is easily solvable with plain JavaScript (see RobG's answer), I wanted to show you the Moment.js solution since you tagged your questions as "momentjs":
moment().seconds(0).milliseconds(0).toISOString();
This gives you the current datetime, without seconds or milliseconds.
Working example: http://jsbin.com/bemalapuyi/edit?html,js,output
From the docs: http://momentjs.com/docs/#/get-set/
A non-library regex to do this:
new Date().toISOString().replace(/.\d+Z$/g, "Z");
This would simply trim down the unnecessary part. Rounding isn't expected with this.
A bit late here but now you can:
var date = new Date();
this obj has:
date.setMilliseconds(0);
and
date.setSeconds(0);
then call toISOString() as you do and you will be fine.
No moment or others deps.
Pure javascript solutions to trim off seconds and milliseconds (that is remove, not just set to 0). JSPerf says the second funcion is faster.
function getISOStringWithoutSecsAndMillisecs1(date) {
const dateAndTime = date.toISOString().split('T')
const time = dateAndTime[1].split(':')
return dateAndTime[0]+'T'+time[0]+':'+time[1]
}
console.log(getISOStringWithoutSecsAndMillisecs1(new Date()))
function getISOStringWithoutSecsAndMillisecs2(date) {
const dStr = date.toISOString()
return dStr.substring(0, dStr.indexOf(':', dStr.indexOf(':')+1))
}
console.log(getISOStringWithoutSecsAndMillisecs2(new Date()))
This version works for me (without using an external library):
var now = new Date();
now.setSeconds(0, 0);
var stamp = now.toISOString().replace(/T/, " ").replace(/:00.000Z/, "");
produces strings like
2020-07-25 17:45
If you want local time instead, use this variant:
var now = new Date();
now.setSeconds(0, 0);
var isoNow = new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString();
var stamp = isoNow.replace(/T/, " ").replace(/:00.000Z/, "");
Luxon could be your friend
You could set the milliseconds to 0 and then suppress the milliseconds using suppressMilliseconds with Luxon.
DateTime.now().toUTC().set({ millisecond: 0 }).toISO({
suppressMilliseconds: true,
includeOffset: true,
format: 'extended',
}),
leads to e.g.
2022-05-06T14:17:26Z
You can use the startOf() method within moment.js to achieve what you want.
Here's an example:
var date = new Date();
var stringDateFull = moment(date).toISOString();
var stringDateMinuteStart = moment(date).startOf("minute").toISOString();
$("#fullDate").text(stringDateFull);
$("#startOfMinute").text(stringDateMinuteStart);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.2/moment.js"></script>
<p>Full date: <span id="fullDate"></span></p>
<p>Date with cleared out seconds: <span id="startOfMinute"></span></p>
let date = new Date();
date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
I hope this works!!
To remove the seconds and milliseconds values this works for me:
const date = moment()
// Remove milliseconds
console.log(moment.utc(date).format('YYYY-MM-DDTHH:mm:ss[Z]'))
// Remove seconds and milliseconds
console.log(moment.utc(date).format('YYYY-MM-DDTHH:mm[Z]'))
We can do it using plain JS aswell but working with libraries will help you if you are working with more functionalities/checks.
You can use the moment npm module and remove the milliseconds using the split Fn.
const moment = require('moment')
const currentDate = `${moment().toISOString().split('.')[0]}Z`;
console.log(currentDate)
Refer working example here:
https://repl.it/repls/UnfinishedNormalBlock
In case for no luck just try this code
It is commonly used format in datetime in the SQL and PHP
e.g.
2022-12-25 19:13:55
console.log(new Date().toISOString().replace(/^([^T]+)T([^\.]+)(.+)/, "$1 $2") )

How to get the Australian Time Zone using Javascript? (Not JQuery)

I am trying to help a friend to get the Australian Time Zone for the University Assignment and finding difficulty.
Could someone point us in the right direction?
Thank you!
<script>
function Timezone() {
var x = new Date();
var currentTimeZoneOffsetInHours = x.getTimezoneOffset() / 60;
document.getElementById("add").innerHTML = currentTimeZoneOffsetInHours;
}
</script>
<p id="add"></p>
You simply use
let AuDate = new Date().toLocaleString("en-US", {timeZone: "Australia/Sydney"});
By looking at your code, looks like you are trying to get the current date and time of an Australian timezone. Lets say you want Australian Eastern Standard Time (AEST) and you want the date displayed how they would in Australia DD-MM-YYYY then do the following:
var timestamp_UTC = new Date();
var readable_timestamp_AEST = timestamp_UTC.toLocaleDateString("en-AU", {timeZone: "Australia/Sydney"}).replace(/\//g, "-") + ' ' + somestamp.toLocaleTimeString("en-AU", {timeZone: "Australia/Sydney"});
"en-AU" is the locales argument which tells the toLocalDateString to display the date as DD-MM-YYYY and the second argument is for options (timeZone is just one such possible option). Info about toLocalDateString function can be found here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString
Here is some information about the Date() function https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
Hope this clears up a few things around getting times and dates from the Date() function.
I think i understand what you mean. But before that i'd like to make 2 points:
1: The Timezone() function should be called somewhere.
<script>
function Timezone() {
var x = new Date();
var currentTimeZoneOffsetInHours = x.getTimezoneOffset() / 60;
document.getElementById("add").innerHTML = currentTimeZoneOffsetInHours;
}
Timezone();
</script>
2: The convention usually is that methods start with a lower case letter. Maybe updateTimezone() would be more appropriate.
Your question can be interpreted in 2 ways now:
you want your timezone's offset in hours and for this the code above should work. getTimezoneOffset() is the way to go.
you want a human readable name of your timezone, as you can see on my site currentmillis.com (in my case it says GTB Summer). You can look in my source code to see how i achieve this:
var s = date.toString();
var iOfP = s.indexOf('('); // index of parenthesis
if (iOfP < 0) {
s = s.substring(s.lastIndexOf(' ') + 1);
} else {
s = s.substring(iOfP+1, s.length-1);
}
if (s.length > 4 && s.lastIndexOf(" Time") == s.length-5){
s = s.substring(0, s.length-5);
}
timezoneM.innerHTML = s;
This works because when you call toString() on the date the result should contain the full name of your timezone: w3schools.com/jsref/jsref_tostring_date.asp

creating date from a timestring in javascript

I am new to javascript and am trying to compare two date values ,I am getting two time value strings in the format
06:30:47 AM
01:10:47 PM
I need to compare these to find out if the first one is less than the other.I couldn't figure out how to do this in javascript.Can someone help?
o.h
I do not think that the standard implementation can parse this. I would do something like this:
function toDate(dateString) {
var timeComponents = dateString.replace(/\s.*$/, '').split(':');
if (dateString.indexOf("PM") > -1) {
timeComponents[0] += 12;
}
var date = new Date();
date.setHours(timeComponents[0]);
date.setMinutes(timeComponents[1]);
date.setSeconds(timeComponents[2]);
return date;
}
if (toDate('06:30:47 AM') > toDate('01:10:47 PM')) {
// ...
}
JavaScript's specified date/time parsing, what you can rely upon cross-browser, is surprisingly limited. For a long time, there was no single string date format that was mandated in the spec, and as of the recent 5th edition spec, the only mandated format is ISO-8601 (and some subsets). You can't yet rely on browsers having implemented that part of the 5th edition spec.
So you have a couple of choices:
Parse the string yourself and use the Date constructor that takes the individual parts of the date as numbers, e.g. new Date(year, month, day, hour, minute, second, ...). (You need only specify as many of those as you want, so for instance new Date(2010, 9, 14) is September 14th, 2010.)
Use a library like Moment that's already done the work for you. Moment lets you specify the format to parse.
Use the Date object. Check this: http://www.w3schools.com/jsref/jsref_obj_date.asp
Try putting the two values in Date variables and do this:
if(var1.valueOf() > var2.valueOf())
{
//Do Something
}
If your times are always in the format 00:00:00 AM then
var a="06:30:47 AM";
var b="01:10:47 PM";
var at=parseInt(a.substring(0,8).replace(/(^0+|:)/g,""));
var bt=parseInt(b.substring(0,8).replace(/(^0+|:)/g,""));
if (a.charAt(9)=="P") {at=at+120000};
if (b.charAt(9)=="P") {bt=bt+120000};
if (at<bt) {
// a is smaller
}
else
{
// a is not smaller
};
..should be cross-browser and time/format safe.
I tried something like this
var ts1="06:30:47 AM";
var ts2="01:10:47 PM";
var ds=new Date().toDateString();
var d1=new Date(ds+" "+ts1);
var d2=new Date(ds+" "+ts2);
if (!(d2>d1)){
alert("d1 should be less than d2");
}
Is there something wrong with this?
// specific formatter for the time format ##:##:## #M
var formatToMiliseconds = function(t){
t = t.split(/[:\s]/);
t = ((t[0] * 3600000) + (t[1] * 60000) * (t[2] * 1000)); // To ms
t = t + (/PM/i.test(t[3]) ? 43200000 : 0); // adjust for AM/PM
return t;
}
var time01 = formatToMiliseconds('06:30:47 AM');
var time02 = formatToMiliseconds('01:10:47 PM');
alert(time01 > time02); // false
allert(time01 < time02); // true
As a bonus, your time is now more compatible with the Date object and other time calculations.

Categories

Resources