I am working on a script in which I am trying to use Arrays & Map Method to add numdays to an array in google Sheets.
The following image is an example of the data
function new_date() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastRow = ss.getMaxRows();
var data = ss.getRange(2, 5, lastRow).getValues();
// Logger.log(data)
var newData = data.map(adding_days);
ss.getRange(2, 5, lastRow).setValues(newData);
}
function adding_days(row){
var millis_per_day = 1000 * 60 * 60 * 24;
var days = 7 ;
var date = new Date(row[0]);
var date2 = Utilities.formatDate(date, "GMT+05:30" , "MM-dd-yyyy");
var numdays = days * millis_per_day
return [ date2 + numdays ];
}
When I run the code its only returning the data again in another format, I dont understand why its not being able to add the numdays to the data. I am new to using arrays in app script so I am very confused about whats going wrong here.
Thanks in advance!
Adding years, months, days, hours, minutes, seconds and milliseconds to a date
In this particular case days:
function new_date() {
const ss=SpreadsheetApp.getActive()
const sh=ss.getActiveSheet();
const v=sh.getRange(2,5,sh.getLastRow()-1,1).getValues();
const ndt=v.map(function(r,i){
let dt=new Date(r[0]);
let days=7;
return [new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()+days,dt.getHours(),dt.getMinutes(),dt.getMilliseconds())];
});
sh.getRange(2,5,ndt.length,ndt[0].length).setValues(ndt);
}
The problem with adding in milliseconds to the date value is that it does compensate for special situations like leap years and such. While this requires one very long line it now allows you to add numbers of days and hours and such directly to the date with simple integer math by adding it to the appropriate section of the date constructor.
Date Constructor
Related
This question already has answers here:
Difference between two dates in years, months, days in JavaScript
(34 answers)
How to get difference between 2 Dates in Years, Months and days using moment.js
(3 answers)
How to get the difference of two dates in mm-dd-hh format in Javascript
(3 answers)
Closed 2 years ago.
I am trying to get the difference between two dates (my birthday and the current date to get the time left until my birthday), But I want the output format in ('Year/Months/Days); How can I do that? that's what I've tried so far :
const birthday = new Date ('11-20-2021').getTime();
const today = new Date ().getTime();
const dys = (1000*60*60*24);
const months = (dys*30);
let differance = birthday-today ;
const formatted = Math.round(differance/dys);
console.log(formatted);`
thank you in advance
How do you feel about the modulo operator? :)
This is a common math operation, like finding change or such. Think of it this way, if you have a large number of days, say 397, you can get number of years by doing integer division (1), then you can get the number of days left by doing modulo by a year to get the remainder (in days) 397%365 = 32. Then you can repeat the process to get number of months remaining (1...assuming 30 day month) in that and again, modulo to get the final number of days 2 ...
I'm no javascript pro, but I think you need to use Math.floor(quotient) to get the result of division in integer format.
this example compares between the current date and the date 2100/0/14 try the same concept in the example and i hope it helps:
var today, someday, text;
today = new Date();
someday = new Date();
someday.setFullYear(2100, 0, 14);
if (someday > today) {
text = "Today is before January 14, 2100.";
} else {
text = "Today is after January 14, 2100.";
}
document.getElementById("demo").innerHTML = text;
Working with dates and differences can be difficult because there are a lot of edge cases. which is why I prefer to let a dedicated library handle this, like https://momentjs.com/
moment has a plugin (https://www.npmjs.com/package/moment-precise-range-plugin) which does exactly what you are looking for:
import moment from 'moment';
import 'moment-precise-range-plugin';
var m1 = moment('2014-01-01 12:00:00','YYYY-MM-DD HH:mm:ss');
var m2 = moment('2014-02-03 15:04:05','YYYY-MM-DD HH:mm:ss');
var diff = moment.preciseDiff(m1, m2, true); // {years : 0, months : 1, days : 2, hours : 3, minutes : 4, seconds : 5}
var str = `Years: ${diff.years}, Months: ${diff.months}, Days: ${diff.days} `; // 'Years: 0, Months: 1, Days: 2'
If I got you right, I've done it this way.
Haven't touched your original code, but added a function that calculates the dateTime output of the total days of difference.
const birthday = new Date('11-20-2021').getTime();
const today = new Date().getTime();
const dys = (1000 * 60 * 60 * 24);
const months = (dys * 30);
let totalDayserance = birthday - today;
const formatted = daysToDateTime(totalDayserance / dys);
console.log(formatted);
function daysToDateTime(totalDays) {
var baseVal = '';
var formedValues = [
['Years', 365],
['Months', 30],
['Days', 1]
];
for (var i = 0; i < formedValues.length; i++) {
var valueByGroup = Math.floor(totalDays / formedValues[i][1]); //by months
if (valueByGroup >= 1) {
baseVal += (valueByGroup + formedValues[i][0]) + ', ';
totalDays -= valueByGroup * formedValues[i][1];
}
}
return baseVal;
}
I am trying to get moment.js to show me time until a specific date. I have that done doing this:
let date = 2017-03-27T12:00:00;
moment().to(date);
This shows: "in 10 days".
I'd really like this to show "in 10 days and 2 hours" or the two highest values. For example, 1 year and 5 months, 4 minutes and 30 seconds.
Is there a simple way to do this? I am currently working on a complicated method to handle this...
let years = moment(date).local().diff(moment(), 'years');
let months = (moment(date).local().diff(moment(), 'months'));
let days = (moment(date).local().diff(moment(), 'days'));
let hours = (moment(date).local().diff(moment(), 'hours'));
let minutes = (moment(date).local().diff(moment(), 'minutes'));
let seconds = (moment(date).local().diff(moment(), 'seconds'));
//The above values return total number each,
//For example, this could show 1 year, 14 months, 435 days, etc.
//The math below is supposed to make this say
//1 year, 2 months, 14 days, etc.
let yearsRemain = years;
let monthsRemain = months - (years *12);
let daysRemain = days - (Math.floor(months * 30));
let hoursRemain = hours - (days * 24);
let minutesRemain = minutes - (hours * 60);
let secondsRemain = seconds - (minutes * 60);
var dateArray = [
yearsRemain,
monthsRemain,
daysRemain,
hoursRemain,
minutesRemain,
secondsRemain
]
console.log(dateArray);
/*
returns [1, 1, 3, 23, 16, 46] for example
*/
the problem with this is when it comes to days. Since days in a year and days in a month vary, I was hoping moment.js would help me out. Is there a better way of doing this?
Eventually, I will be able to iterate through the array and find the two largest values to display how I'd like.
You can use moment.duration to calculate the dateArray value. Duration has years(), months(), days(), hours(), minutes(), seconds() getters.
Here a live example:
let date = '2017-03-27T12:00:00';
var dur = moment.duration( moment(date).diff(moment()) );
let yearsRemain = dur.years();
let monthsRemain = dur.months();
let daysRemain = dur.days();
let hoursRemain = dur.hours();
let minutesRemain = dur.minutes();
let secondsRemain = dur.seconds();
var dateArray = [
yearsRemain,
monthsRemain,
daysRemain,
hoursRemain,
minutesRemain,
secondsRemain
]
console.log(dateArray);
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
You can use moment-duration-format plug-in to show duration in a custom format. The plugin has a template option that lets you customize the format.
let date = '2017-03-27T12:00:00';
let dur = moment.duration( moment(date).diff(moment()) );
console.log( dur.format() );
console.log( dur.format('M [months and] d [days]') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-duration-format/1.3.0/moment-duration-format.min.js"></script>
Note that moments has relativeTime, relativeTimeRounding and relativeTimeThreshold that lets you customize how moment shows relative time (so you can change to output).
I have to simply calculate difference between two dates, and display it as integer but my code below gives errors if there are large amount of dates (more than 26) in between 2 dates, as well as if there is a date "31st" of a month in between 2 dates.
Can not find whats wrong with my code...?
The values of 'ires_sakuma_datums' and 'ires_beigu_datums' are set by jquery calendar picker and are displayed in the format e.g. 25-08-2012 and 17-09-2012 respectively and the result should be displayed into id 'dienu_skaits'
Example 'ires_sakuma_datums' is set to 28-08-2012 and 'ires_beigu_datums' is set to 29-09-2012 and it results into 31.041666666666668 although I would expect to result into 32
function getDays()
{
var x = document.getElementById('ires_sakuma_datums').value;
var y = document.getElementById('ires_beigu_datums').value;
//assuming that the delimiter for dt time picker is a '-'.
var arr1 = x.split('-');
var arr2 = y.split('-');
var dt1 = new Date();
dt1.setFullYear(arr1[2], arr1[1], arr1[0]);
var dt2 = new Date();
dt2.setFullYear(arr2[2], arr2[1], arr2[0]);
document.getElementById('dienu_skaits').value = (dt2.valueOf() - dt1.valueOf()) / (60 * 60 * 24 * 1000);
document.forms['test'].elements['dienu_skaits'].focus();
}
The problem is that months to be passed to Date are 0 based , so you have to subtract 1 from the month. http://jsfiddle.net/qB9V3/5/ Therefore, your comparison between 28-08-2012 and 29-09-2012 was actually diffing 28-09-2012 and 29-10-2012
So your code would need to change to be
var arr1 = x.split('-');
var arr2 = y.split('-');
var dt1 = new Date();
dt1.setFullYear(arr1[2], parseInt(arr1[1],10) -1, arr1[0]);
var dt2 = new Date();
dt2.setFullYear(arr2[2], parseInt(arr2[1],10) - 1, arr2[0]);
Beware that if your dates cross daylight savings changes, the number of days in between won't be even, so you'll need to round the result
document.getElementById('dienu_skaits').value = Math.round(
(dt2 - dt1) / (60 * 60 * 24 * 1000)
);
I have two input dates taking from Date Picker control. I have selected start date 2/2/2012 and end date 2/7/2012. I have written following code for that.
I should get result as 6 but I am getting 5.
function SetDays(invoker) {
var start = $find('<%=StartWebDatePicker.ClientID%>').get_value();
var end = $find('<%=EndWebDatePicker.ClientID%>').get_value();
var oneDay=1000 * 60 * 60 * 24;
var difference_ms = Math.abs(end.getTime() - start.getTime())
var diffValue = Math.round(difference_ms / oneDay);
}
Can anyone tell me how I can get exact difference?
http://momentjs.com/ or https://date-fns.org/
From Moment docs:
var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
a.diff(b, 'days') // =1
or to include the start:
a.diff(b, 'days')+1 // =2
Beats messing with timestamps and time zones manually.
Depending on your specific use case, you can either
Use a/b.startOf('day') and/or a/b.endOf('day') to force the diff to be inclusive or exclusive at the "ends" (as suggested by #kotpal in the comments).
Set third argument true to get a floating point diff which you can then Math.floor, Math.ceil or Math.round as needed.
Option 2 can also be accomplished by getting 'seconds' instead of 'days' and then dividing by 24*60*60.
If you are using moment.js you can do it easily.
var start = moment("2018-03-10", "YYYY-MM-DD");
var end = moment("2018-03-15", "YYYY-MM-DD");
//Difference in number of days
moment.duration(start.diff(end)).asDays();
//Difference in number of weeks
moment.duration(start.diff(end)).asWeeks();
If you want to find difference between a given date and current date in number of days (ignoring time), make sure to remove time from moment object of current date as below
moment().startOf('day')
To find difference between a given date and current date in number of days
var given = moment("2018-03-10", "YYYY-MM-DD");
var current = moment().startOf('day');
//Difference in number of days
moment.duration(given.diff(current)).asDays();
Try this Using moment.js (Its quite easy to compute date operations in javascript)
firstDate.diff(secondDate, 'days', false);// true|false for fraction value
Result will give you number of days in integer.
Try:
//Difference in days
var diff = Math.floor(( start - end ) / 86400000);
alert(diff);
This works for me:
const from = '2019-01-01';
const to = '2019-01-08';
Math.abs(
moment(from, 'YYYY-MM-DD')
.startOf('day')
.diff(moment(to, 'YYYY-MM-DD').startOf('day'), 'days')
) + 1
);
I made a quick re-usable function in ES6 using Moment.js.
const getDaysDiff = (start_date, end_date, date_format = 'YYYY-MM-DD') => {
const getDateAsArray = (date) => {
return moment(date.split(/\D+/), date_format);
}
return getDateAsArray(end_date).diff(getDateAsArray(start_date), 'days') + 1;
}
console.log(getDaysDiff('2019-10-01', '2019-10-30'));
console.log(getDaysDiff('2019/10/01', '2019/10/30'));
console.log(getDaysDiff('2019.10-01', '2019.10 30'));
console.log(getDaysDiff('2019 10 01', '2019 10 30'));
console.log(getDaysDiff('+++++2019!!/###10/$$01', '2019-10-30'));
console.log(getDaysDiff('2019-10-01-2019', '2019-10-30'));
console.log(getDaysDiff('10-01-2019', '10-30-2019', 'MM-DD-YYYY'));
console.log(getDaysDiff('10-01-2019', '10-30-2019'));
console.log(getDaysDiff('10-01-2019', '2019-10-30', 'MM-DD-YYYY'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js"></script>
Also you can use this code: moment("yourDateHere", "YYYY-MM-DD").fromNow(). This will calculate the difference between today and your provided date.
// today
const date = new Date();
// tomorrow
const nextDay = new Date(new Date().getTime() + 24 * 60 * 60 * 1000);
// Difference in time
const Difference_In_Time = nextDay.getTime() - date.getTime();
// Difference in Days
const Difference_In_Days = Difference_In_Time / (1000 * 3600 * 24);
Let's say I have
a = "2011-11-09 08:00:00"
b = "2011-11-10 08:30:00"
What's the best way of finding how many days, hours, minutes the difference between these two timestamps are in Javascript?
So the output should be "1 day" (ignore the minutes since there is a larger unit (day) in the difference) ?
The only reliable way to convert a string to a date in javascript is to parse it manually. If the format is consistent with what you have posted, then you can convert it to a date as follows:
function stringToDate(s) {
var dateParts = s.split(' ')[0].split('-');
var timeParts = s.split(' ')[1].split(':');
var d = new Date(dateParts[0], --dateParts[1], dateParts[2]);
d.setHours(timeParts[0], timeParts[1], timeParts[2])
return d
}
so you can do:
var a = "2011-11-09 08:00:00"
var b = "2011-11-10 08:30:00"
alert(stringToDate(a) - stringToDate(b));
to get the difference in milliseconds. However, the difference in days between two dates may not be a simple matter of dividing the difference by 8.64e7 (milliseconds in one da). You need to confirm the business logic in regard to that.
EDITED to work in any browser
var matchDate = /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/;
var firstDateParsed = matchDate.exec("2011-11-09 08:00:00");
var secondDateParsed = matchDate.exec("2011-11-10 08:30:00");
var a = new Date(firstDateParsed[1], firstDateParsed[2], firstDateParsed[3], firstDateParsed[4], firstDateParsed[5], firstDateParsed[6], 0);
var b = new Date(secondDateParsed[1], secondDateParsed[2], secondDateParsed[3], secondDateParsed[4], secondDateParsed[5], secondDateParsed[6], 0);
var differenceInMilliseconds = a.getTime() - b.getTime();
// minutes
alert(differenceInMilliseconds / 1000 / 60);
// hours
alert(differenceInMilliseconds / 1000 / 60 / 60);
// days
alert(differenceInMilliseconds / 1000 / 60 / 60 / 24);
Tested in IE and Firefox as well as Chrome: http://jsfiddle.net/xkBTS/4/
You'll have to parse the timestamp to a date yourself:
function parseMySQLTimestamp(timestamp) {
var parts = timestamp.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
return new Date(+parts[1], (+parts[2] - 1), +parts[3], +parts[4], +parts[5], +parts[6]);
}
Get the difference in milliseconds by subtracting one date from the other:
var msDifference = parseMySQLTimestamp(b) - parseMySQLTimestamp(a);
Simple arithmetic will let you convert milliseconds to seconds, minutes, or whatever.
By the way, this function will throw an error if a timestamp is passed in that doesn't match the expression. From a software design point of view, this behavior makes sense to me. However, if you want to be able to use that function with strings that may not be in the correct format, you can just do a null check against parts and return null if there is no match.