Related
I'm trying to write a script to subtract 5 days from a defined date but seems not working, here's my code:
var End_Day = sheet.getRange(i + 2, 20).getValue();
Logger.log(End_Day);
var End_day_2 = new Date();
End_day_2.setDate(End_Day.getDate()-5);
Logger.log(End_day_2);
and the result is not just - 5 days:
11:18:47 AM Info Sat Jun 04 00:00:00 GMT+08:00 2022
11:18:47 AM Info Fri Apr 29 11:18:47 GMT+08:00 2022
I am quite confused why the date move from Jun to Apr.
Thanks for having a look
Try:
var End_Day = sheet.getRange(i + 2, 20).getValue();
var End_day_2 = new Date(End_Day.getTime() - (5 * (1000 * 60 * 60 * 24)))
Logger.log(End_Day);
Logger.log(End_day_2);
Function:
const endDay = sheet.getRange(i + 2, 20).getValue()
const endDay2 = DateFromDaysAgo(endDay, 5)
...
function DateFromDaysAgo(startDate, number) {
if (typeof startDate === `string`) { startDate = new Date(startDate) }
return new Date(startDate.getTime() - (number * (1000 * 60 * 60 * 24)))
}
You should learn more about Date.prototype.setDate().It only changes the day of the month of a given Date instance.
As the code you posted, the day of the month of End_Day is 4, End_day_2.setDate(4 - 5) equals to End_day_2.setDate(-1) and the month of End_day_2 is April according to the console result, because there're 30 days in April, setDate(-1) means setDate(29), so you got Apr 29 at the end. That's how it goes.
One right way to do is substracting 5 days worth of milliseconds.
function addDays(date, days){
const DAY_IN_MILLISECONDS = 24 * 60 * 60000;
return new Date(date.getTime() + days * DAY_IN_MILLISECONDS);
}
console.log(addDays(new Date(), -5).toString()); // 5 days ago
I am quite confused why the date move from Jun to Apr.
It's because you're setting date on today(End_day_2) and not on your predefined date(End_day).
Change
End_day_2.setDate(End_Day.getDate()-5);
to
End_Day.setDate(End_Day.getDate()-5);
console.info(End_Day);
If what's coming from the sheet is a string, you will have to convert the date string into a date object.
The other thing is you have to work in milliseconds as #vanowm says:
606024*5 = 432000 * 1000 = 432000000
so skipping the sheet entirely:
x = new Date
> Fri May 27 2022 11:24:01 GMT-0400 (Eastern Daylight Time)
y = new Date(x - 432000000)
> Sun May 22 2022 11:24:01 GMT-0400 (Eastern Daylight Time)
This will do the trick. Works with any date and can subtract any number of days
const subtractDays = (fromDate, numDays) => {
if (!(fromDate instanceof Date)) throw 'The first argument must be a date';
return new Date(new Date().setDate(fromDate.getDate() - +numDays));
};
Weekago
function weekago() {
let dt = new Date();
dt.setDate(dt.getDate()-7);
Logger.log(dt);
return dt;
}
Five days ago
function fiveago() {
let dt = new Date();
dt.setDate(dt.getDate()-5)
Logger.log(dt);
return dt;
}
Five days from a date in a spreadsheet cell
function fivefromadateinspreadsheet() {
const v = SpreadsheetApp.getActiveSheet().getRange("A1").getValue();
let dt = new Date(v);
dt.setDate(dt.getDate()-5);//Note that does not return a date it return the numbrer of milliseconds
Logger.log(dt);
return dt;
}
You can subtract 5 days from a defined date in Google App Script by using the Utilities.formatDate() method. Here's an example:
function subtractDays() {
var date = new Date();
var subtractDays = 5;
// Subtract 5 days from the current date
date.setDate(date.getDate() - subtractDays);
// Format the new date
var newDate = Utilities.formatDate(date, "UTC", "yyyy-MM-dd");
Logger.log(newDate);
}
In this example, we first create a Date object to represent the current date. Then, we subtract 5 days from the current date by using the setDate() method. Finally, we format the new date using the Utilities.formatDate() method and log it to the console using the Logger.log() method.
You can modify the subtractDays variable to subtract a different number of days from the date, or you can use a different date object to start with.
I'm supposed to write a code for codewars to find out the number of times a month ends with a Friday within a range of years.
To start off, I did research and found out several solutions but I still couldn't figure out the results in the console.log.
The first solution is from this tutorial:
In this code, the solution is
let LastDay = new Date(1998, 5 + 1, 0).getDate();
I was able to get the date, but it wasn't clear which day the date falls upon.
Then I found another solution at w3schools. This solution also set the date to be the last day of this month:
var d = new Date();
d.setMonth(d.getMonth() +1, 0);
document.getElementById("demo").innerHTML = d;
However, it works if it displays it as innerHTML = Sat Nov 30 2019 00:57:09 GMT-0500 (Eastern Standard Time). However, when I tried to rewrite the code and console.log it like in this example:
let d = new Date();
let month = d.getMonth()+1;
let lastday = d.setMonth(month, 0);
console.log(lastday);
The result I got was 1575093343211. I don't understand how it displays those numbers instead of the dates I was expecting. I thought that if it does display the dates, starting with the day, I can convert the date to string or array and check if the first element is Friday and then add it to the counter in the code I'm writing. How do I get the code to display the way I want it to.
something like this will work...
function LastDayOfMonth(Year, Month) {
return new Date((new Date(Year, Month, 1)) - 1);
}
var d = LastDayOfMonth(new Date().getYear(), new Date().getMonth())
//var d = LastDayOfMonth(2009, 11)
var dayName = d.toString().split(' ')[0];
console.log(dayName)
The result I got was 1575093343211. I don't understand how it displays those numbers instead of the dates I was expecting
Because you console.log the output of the setMonth method, not the date object:
let lastday = d.setMonth(month, 0);
console.log(lastday);
According to the documentation, the setMonth method returns:
The number of milliseconds between 1 January 1970 00:00:00 UTC and the updated date.
Instead you should use that output to create a new instance of the date object:
let lastday = new Date(d.setMonth(month, 0));
console.log(lastday);
Algorithms to get the last day of the month are generally based on setting a date to day 0 of the following month, which ends up being the last day of the required month.
E.g. to get the last day for June, 2019 (noting that 6 is July, not June):
let endOfJune = new Date(2019, 6, 0):
Once you have the date, you can get the day where 0 is Sunday, 1 is Monday, etc. and 5 is Friday:
let endOfJuneDay = endOfJune.getDay();
The set* methods modify the Date they're called on and return the time value for the modified date. So you don't need to assign the result to anything:
let d = new Date();
let month = d.getMonth() + 1;
// Set date to the new month
d.setMonth(month, 0);
console.log(d);
So if you want to loop over the months for a range of years and get the number that end with a Friday (or any particular day), you might loop over the months something like:
/*
** #param {number} startYear - start year of range
** #param {number} endYear - end year of range
** #param {number} dat - day number, 0 = Sunday, 1 = Monday, etc.
** default is 0 (Sunday)
*/
function countEOMDay(startYear, endYear, day = 0) {
// startYear must be <= end year
if (startYear > endYear) return;
// Start on 31 Jan of start year
let start = new Date(startYear, 0, 31);
// End on 31 Dec of end year
let end = new Date(endYear, 11, 31);
let count = 0;
// Loop over months from start to end
while (start <= end) {
// Count matching days
if (start.getDay() == day) {
++count;
}
// Increment month to end of next month
start.setMonth(start.getMonth() + 2, 0);
}
return count;
}
console.log(countEOMDay(2019, 2019, 5)); // 1
console.log(countEOMDay(2018, 2019, 5)); // 3
You can use setMonth() method to set the month of a date object. The return value of setMonth() method is milliseconds between the date object and midnight January 1 1970. That's what you get from console.log(lastday);
Your return value,
1575093343211
is milliseconds between your date object (d) and midnight January 1 1970.
If you want to get the expected date, you have to console log your date object instead the lastday, as follows:
let d = new Date();
let month = d.getMonth()+1;
let lastday = d.setMonth(month, 0);
console.log(d);
output: Sat Nov 30 2019 00:02:47 GMT+0530 (India Standard Time)
This is an alternative solution I wrote to solve your problem. This will return the number of times a month ends with a Friday within a range of years. Hope this will help you :)
var days = [];
var count = 0;
function getLastFridaysCount(startYear, endYear) {
for (var year = startYear; year <= endYear; year++) {
days = [
31,
0 === year % 4 && 0 !== year % 100 || 0 === year % 400 ? 29 : 28,
31, 30, 31, 30, 31, 31, 30, 31, 30, 31
];
for (var month = 0; month <= 11; month++) {
var myDate = new Date();
myDate.setFullYear(year);
myDate.setMonth(month);
myDate.setDate(days[month]);
if(myDate.getDay() == 5)
{
count++;
}
}
}
return count;
}
console.log("count", getLastFridaysCount(2014, 2017));
this is the solution, in the code can find the comments "//" explaining of what happens in each iteration.
function lastDayIsFriday(initialYear, endYear) {
let count = 0;
//according to when the year ends starts the loop
if (endYear !== undefined) {
let start = new Date(initialYear, 0, 31);
let end = new Date(endYear, 11, 31);
while(start <= end) { //check if the start date is < or = to the end
//The getDay() method returns the day of the week (from 0 to 6) for the specified date.
if(start.getDay() === 5) { //if = to FriYAY!!!
count++; //count the day
}
start.setMonth(start.getMonth()+2, 0);// returns the month (from 0 to 11) .getMonth
} //& sets the month of a date object .setMonth
return count;
} else {
let start = new Date(initialYear, 0, 31);
console.log(start.toString());
for(let i = 0; i < 12; i++) {
if(start.getDay() === 5) {
count++;
}
start.setMonth(start.getMonth() + 2, 0);
// console.log(start.toString());
}
return count;
}
}
I want to create timestamp list grouped by X minutes.
For instance I have min data value and max date timestamp value.
minDate = 1524548466000; // Tuesday, April 24, 2018 5:41:06 AM
maxDate = 1524577986000; // Tuesday, April 24, 2018 1:53:06 PM
So I want to create timestamp array start with Tuesday, April 24, 2018 5:40:0 AM to Tuesday,April 24, 2018, 1:55:00 PM using javascript.
I want this output:
[1524548400000,1524548700000,1524549000000,...1524578100000]
How can I do this?
Here is my solution. I just count second and compare with maxDate.
var minDate = new Date(1524548466000); // Tuesday, April 24, 2018 5:41:06 AM
var maxDate = new Date(1524577986000); // Tuesday, April 24, 2018 1:53:06 PM
var listTimestamp = [];
while (minDate.getTime() !== maxDate.getTime()) {
minDate.setSeconds(minDate.getSeconds() + 1);
listTimestamp.push(minDate.getTime());
}
console.log(listTimestamp);
Here the function you needed
function timestampGrouping(minDate, maxDate, x){
var gap = x * 60000 //60000 = 1minute;
minDate = Math.floor(minDate/gap)*gap;
maxDate = Math.ceil(maxDate/gap)*gap;
var arr = [];
while(minDate <= maxDate){
arr.push(minDate);
minDate += gap;
}
return arr;
}
var groupingArr = timestampGrouping(1524548466000, 1524577986000, 5);
console.log(groupingArr);
Math.floor and Math.ceil is to find the nearest gap value you required, and just loop thought the value to get all the minute gap you want.
minDate, maxDate and gap value can be anything you wish to.
Hope this is what you required.
You could divide the given Unix Time (Epoch Time) and divide it by a product of wanted minutes, seconds and 1000 for miliseconds.
5 minutes * 60 seconds * 1000 milliseconds = 300000
For moving events in the same slot use
Math.floor(time / 300000)
if duration is 5 min then you can set duration variable as follows.
var duration = 5 * 60 * 1000;
endTime = endTime - endTime % duration;
startTime = startTime - startTime % duration;
for(var i=startTime;i<endTime;i+=duration){
arr.push(i);
}
Ive been searching quite a lot find an answer for this , and couldn't find one.
I have 2 dates ,
I want to calc days between them
but I Also want the end day to be counted.
Example :
me and my wife go to hotel from [20 jan] till [26 Jan] , so its 7 days total.
the only code which I find working is :
Math.round((b - a) / ( 1000 * 60 * 60 * 24)) +1
where :
var a= new Date (y,0,20);
var b= new Date (y,0,26);
I also made a nested loop to test all months within a 150 years , and it works Ok.
var y = 1970;
var m = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
for(var i = 0; i < 150; i++)
{
for(var j = 0; j < 12; j++)
{
var a = new Date(y + i, m[j], 20);
var b = new Date(y + i, m[j], 26);
var days = Math.round((b - a) / (1000 * 60 * 60 * 24)) + 1;
if(days != 7) console.log(i + y); //tell me if result is unexpected.
}
}
console.log('-FINISH-' + new Date().getTime())
So where is the problem ?
I can't figure how the math function like round can do the trick here.
We are talking about milliseconds here and I can't see where the round behavior gives me the right result.
(p.s. - forget about ceil and floor , they do not help here and have inconsistent results) , I have also tried to add one day to the b value , and use ceil || floor but with no success
here is the code
The reason your rounding is working is because you're only working with full days. myDate.getTime() will yield the number of milliseconds since 1970-01-01. If you're always assigning your dates as new Date(y,m,d) you will always have the time part set to 00:00:00.000, and hence the date comparison will always yield a multiple of 86400000, which is your divisor. The rounding here is for the most part superfluous.
If you're creating all of your dates as specified above, the only time rounding does come into play, is when the daylight savings offset at date b is different from that at date a. round will take care of these discrepancies, as they're rarely more than an hour.
From your script, October 1970 is problematic (in CEST) because Oct 20th is in daylight savings, and Oct 26th isn't.
var a = new Date(1970, 9, 20);
var b = new Date(1970, 9, 26);
(b - a) / (1000 * 60 * 60 * 24) // 6.041666666666667
You could work around this by rounding, or by using UTC dates
var a = new Date(Date.UTC(1970, 9, 20));
var b = new Date(Date.UTC(1970, 9, 26));
(b - a) / (1000 * 60 * 60 * 24) // 6
Here is your answer:
http://www.direct.gov.uk/en/Nl1/Newsroom/DG_185398
Basically, March 25 has 23 hours in it instead of 24. And 28'th October has 25 hours in it. That's why rounding works well while floor/ceil does not.
Also, as you can see, DST date changes with each year (you can see that in same article), that's why only once every 5-10 years the floor/cail test fails. On other years DST is applied to different date, therefore test result appears to be normal.
I found the reason! :) (e.g. year 2035)
Date {Sun Mar 25 2035 00:00:00 GMT+0100 (CET)}
Date {Mon Mar 26 2035 00:00:00 GMT+0200 (CEST)}
Look at the GMT Times one is GMT+0100 (CET) and one is GMT+0200 (CEST)
To get always the result without round you have to use UTC:
var a = Date.UTC(y + i, m[j], 25);
var b = Date.UTC(y + i, m[j], 26);
var days = (b - a) / (1000 * 60 * 60 * 24);
I modified your code slightly to find this bug:
var y = 1970;
var m = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
for(var i = 0; i < 150; i++)
{
for(var j = 0; j < 12; j++)
{
var a = new Date(y + i, m[j], 25);
var b = new Date(y + i, m[j], 26);
var days = (b - a);
if(days != 86400000) console.log(i + y, days); //tell me if result is unexpected.
}
}
1983 90000000
1984 82800000
1988 90000000
...
This was already discussed here:
http://www.webdeveloper.com/forum/archive/index.php/t-5195.html
As already answered in a previous post:
var days = Math.floor(enddate.getTime()-startdate.getTime())/(24*60*60*1000);
I had tried to find some work done but I haven't had luck. Any ideas?
Examples:
Week, 1, 2001 => 2001-01-01
Week, 26, 2007 => 2007-06-01
As Kevin's code does not implement ISO 8601 properly (first day of the first week of year must be a Monday), I've corrected it and ended up with (also check it on jsfiddle):
function firstDayOfWeek(week, year) {
if (year==null) {
year = (new Date()).getFullYear();
}
var date = firstWeekOfYear(year),
weekTime = weeksToMilliseconds(week),
targetTime = date.getTime() + weekTime;
return date.setTime(targetTime);
}
function weeksToMilliseconds(weeks) {
return 1000 * 60 * 60 * 24 * 7 * (weeks - 1);
}
function firstWeekOfYear(year) {
var date = new Date();
date = firstDayOfYear(date,year);
date = firstWeekday(date);
return date;
}
function firstDayOfYear(date, year) {
date.setYear(year);
date.setDate(1);
date.setMonth(0);
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date;
}
/**
* Sets the given date as the first day of week of the first week of year.
*/
function firstWeekday(firstOfJanuaryDate) {
// 0 correspond au dimanche et 6 correspond au samedi.
var FIRST_DAY_OF_WEEK = 1; // Monday, according to iso8601
var WEEK_LENGTH = 7; // 7 days per week
var day = firstOfJanuaryDate.getDay();
day = (day === 0) ? 7 : day; // make the days monday-sunday equals to 1-7 instead of 0-6
var dayOffset=-day+FIRST_DAY_OF_WEEK; // dayOffset will correct the date in order to get a Monday
if (WEEK_LENGTH-day+1<4) {
// the current week has not the minimum 4 days required by iso 8601 => add one week
dayOffset += WEEK_LENGTH;
}
return new Date(firstOfJanuaryDate.getTime()+dayOffset*24*60*60*1000);
}
function assertDateEquals(effectiveDate, expectedDate, description) {
if ((effectiveDate==null ^ expectedDate==null) || effectiveDate.getTime()!=expectedDate.getTime()) {
console.log("assert failed: "+description+"; effective="+effectiveDate+", expected="+expectedDate);
}
}
function assertEquals(effectiveValue, expectedValue, description) {
if (effectiveValue!=expectedValue) {
console.log("assert failed: "+description+"; effective="+effectiveValue+", expected="+expectedValue);
}
}
// expect the first day of year to be a monday
for (var i=1970; i<2050; i++) {
assertEquals(firstWeekOfYear(i).getDay(), 1, "first day of year "+i+" must be a monday"); // 1=Monday
}
// assert some future first day of first week of year; source: http://www.epochconverter.com/date-and-time/weeknumbers-by-year.php
assertDateEquals(firstWeekOfYear(2013), new Date(Date.parse("Dec 31, 2012")), "2013");
assertDateEquals(firstWeekOfYear(2014), new Date(Date.parse("Dec 30, 2013")), "2014");
assertDateEquals(firstWeekOfYear(2015), new Date(Date.parse("Dec 29, 2014")), "2015");
assertDateEquals(firstWeekOfYear(2016), new Date(Date.parse("Jan 4, 2016")), "2016");
assertDateEquals(firstWeekOfYear(2017), new Date(Date.parse("Jan 2, 2017")), "2017");
assertDateEquals(firstWeekOfYear(2018), new Date(Date.parse("Jan 1, 2018")), "2018");
assertDateEquals(firstWeekOfYear(2019), new Date(Date.parse("Dec 31, 2018")), "2019");
assertDateEquals(firstWeekOfYear(2020), new Date(Date.parse("Dec 30, 2019")), "2020");
assertDateEquals(firstWeekOfYear(2021), new Date(Date.parse("Jan 4, 2021")), "2021");
assertDateEquals(firstWeekOfYear(2022), new Date(Date.parse("Jan 3, 2022")), "2022");
assertDateEquals(firstWeekOfYear(2023), new Date(Date.parse("Jan 2, 2023")), "2023");
assertDateEquals(firstWeekOfYear(2024), new Date(Date.parse("Jan 1, 2024")), "2024");
assertDateEquals(firstWeekOfYear(2025), new Date(Date.parse("Dec 30, 2024")), "2025");
assertDateEquals(firstWeekOfYear(2026), new Date(Date.parse("Dec 29, 2025")), "2026");
console.log("All assertions done.");
I included test cases for some dates to check that the first day of the first week of year is a Monday and checked some dates based on http://www.epochconverter.com/date-and-time/weeknumbers-by-year.php
Someone might be still interested in a more contained version:
function firstDayOfWeek (year, week) {
// Jan 1 of 'year'
var d = new Date(year, 0, 1),
offset = d.getTimezoneOffset();
// ISO: week 1 is the one with the year's first Thursday
// so nearest Thursday: current date + 4 - current day number
// Sunday is converted from 0 to 7
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
// 7 days * (week - overlapping first week)
d.setTime(d.getTime() + 7 * 24 * 60 * 60 * 1000
* (week + (year == d.getFullYear() ? -1 : 0 )));
// daylight savings fix
d.setTime(d.getTime()
+ (d.getTimezoneOffset() - offset) * 60 * 1000);
// back to Monday (from Thursday)
d.setDate(d.getDate() - 3);
return d;
}
I took the original idea from Kevin, with some tweaks, coz the original code is returning milliseconds. Here you go:
var d = firstDayOfWeek(9, 2013);
console.log(d.format("yyyy-MM-dd"));
////////////////////////////// Main Code //////////////////////////////
function firstDayOfWeek(week, year) {
if (typeof year !== 'undefined') {
year = (new Date()).getFullYear();
}
var date = firstWeekOfYear(year),
weekTime = weeksToMilliseconds(week),
targetTime = date.getTime() + weekTime - 86400000;
var result = new Date(targetTime)
return result;
}
function weeksToMilliseconds(weeks) {
return 1000 * 60 * 60 * 24 * 7 * (weeks - 1);
}
function firstWeekOfYear(year) {
var date = new Date();
date = firstDayOfYear(date,year);
date = firstWeekday(date);
return date;
}
function firstDayOfYear(date, year) {
date.setYear(year);
date.setDate(1);
date.setMonth(0);
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date;
}
function firstWeekday(date) {
var day = date.getDay(),
day = (day === 0) ? 7 : day;
if (day > 3) {
var remaining = 8 - day,
target = remaining + 1;
date.setDate(target);
}
return date;
}
Take a look at this fiddle. First, it gets the first week of the specified year. This takes into account that according to ISO 8601 the first week of the year is the first week containing a wednesday. Then it adds the weeks to the acquired date and returns the result.
function firstDayOfWeek(week, year) {
var date = firstWeekOfYear(year),
weekTime = weeksToMilliseconds(week),
targetTime = weekTime + date.getTime();
return date.setTime(targetTime);
}