I'm using this code to get timespan/elapsed time between two dates
var timein = new Date(year, month, day, tihh1, timm1, 0);
var timeout = new Date(year, month, day, tohh1, tomm1, 0);
var diff = timeout.getTime() - timein.getTime();
var timespan = new Date(diff);
totalHH = parseInt(totalHH) + parseInt(timespan.getUTCHours());
totalMM = parseInt(totalMM) + parseInt(timespan.getUTCMinutes());
This code works but when the time in is later to time out it's not returning a negative result.
Example:
var timein = new Date(2015, 10, 19, 9, 0, 0); // Oct 19 2015 9:00:00
var timeout = new Date(2015, 10, 19, 8, 0, 0); // Oct 19 2015 8:00:00
// Oct 19 2015 8:00:00 - Oct 19 2015 9:00:00
Expected Result: -1 (Hour)
Actual Result: 23 (Hour)
This code works as expected.
Causes
After substraction, diff will be equal to -3600000 and timespan will be initialized with this value.
new Date(value) constructor creates a Date object equal to the Unix epoch beginning (01/01/1970 00:00:00 UTC) plus value milliseconds. As value is negative in our case, new Date(-3600000) will be evaluated to 31/12/1969 23:00:00 UTC (one hour before the Unix epoch).
Now, you apply timespan.getUTCHours() and it is equal to 23.
Solution
In my opinion, the easiest way in this case is to use a simple math instead of Date objects, because it is not supposed to work this way.
For example, in your case, the result for dates 01 Jan 2015 00:00:00 and 03 Jan 2015 00:00:00 will be 0 while the proper answer is 48 hours.
Just calculate the values based on arithemetics, like this:
function writeHHMM(timein, timeout)
{
var totalMinutes = (timeout - timein) / 60000;
var totalHH = Math.floor(totalMinutes / 60); // Math.floor provides integer only values
var totalMM = Math.floor(totalMinutes % 60); // and cuts off seconds
document.body.innerHTML += "<br/> " + totalHH + " hours, " + totalMM + " minutes";
}
writeHHMM(new Date(2015, 10, 19, 9, 0, 0), new Date(2015, 10, 19, 8, 0, 0));
writeHHMM(new Date(2015, 10, 19, 9, 0, 0), new Date(2015, 10, 21, 9, 0, 0));
writeHHMM(new Date(2015, 10, 19, 9, 0, 0), new Date(2014, 7, 3, 5, 15, 13));
Related
This month (March) has 31 days.
I want to get the last day of the month and instead of get Wed Mar 31 2021 23:59:59 I get Fri Apr 30 2021 23:59:59 look:
let d = new Date()
d.setMonth( d.getMonth() + 1) // April
d.setDate(0) // should bring the 31 of March
d.setHours(23, 59, 59, 999)
console.log(d) // Fri Apr 30 2021 23:59:59 GMT+0300 (IDT)
Why does it happen on date with 31 days?
When tried on different months every month it worked as well, for example:
let d = new Date("2021-02-25") // notice that we point to February
d.setMonth( d.getMonth() + 1)
d.setDate(0)
d.setHours(23, 59, 59, 999)
console.log(d) // Sun Feb 28 2021 23:59:59 GMT+0200 (IST)
Notice that in the second example - which is working good, we get the last day of Feb and GMT+2 (IST) and not GMT+3 (IDT)
Also notice that if I declare it like that: let d = new Date('2021-03-25') it also works good (with specific date, instead of just new Date())
It happens because April only has 30 days.
let d = new Date()
d.setMonth( d.getMonth() + 1) // Actually April 31st -> May 1st.
Try this way:
d.setMonth(d.getMonth(), 0);
second argument 0 will result in the last day of the previous month
Got it!
I set +1 for the month while the current date is 31 and what will happen is that it will jump to 31 of April which doesn't exist and the default date will be 1 in May.
So prev date of 1 in May is 30 of April.
I should set the date to 1 before doing the increment of the month, look:
let d = new Date()
d.setDate(1) // this is the change - important!
d.setMonth( d.getMonth() + 1)
d.setDate(0)
d.setHours(23, 59, 59, 999)
console.log(d) // Wed Mar 31 2021 23:59:59
That way, it will start from 1 of March, inc to 1 of April, and go prev date to last day of March.
Even that it also works, weird:
var date = new Date(), y = date.getFullYear(), m = date.getMonth();
var firstDay = new Date(y, m, 1, 0, 0, 0, 0);
var lastDay = new Date(y, m + 1, 0, 23, 59, 59, 999)
console.log(lastDay)
I am trying to create an array of all dates within a given time frame. For testing purposes, I am using Feb 9 - Feb 13, so the desired array should be [Feb 9, Feb 10, Feb 11, Feb 12, Feb 13]. Thanks to an old post, I learned to use New Date() to create new Date object every time, so that the array doesn't end up like [Feb 13, Feb 13, Feb 13, Feb 13, Feb 13]. But, it is still overwriting the very first element that I push to the array; It is outputting [Feb 10, Feb 11, Feb 12, Feb 13, Feb 13]. I have included a print statement inside my while loop, to track the array after every push, which is how I know the first element is the one getting overwritten. I was hoping for any insight into why this is happening, and how to get my desired array? Any help is much appreciated, thank you!
Here is the code I am using:
var Current_Date = new Date(Date_start) // It starts at Feb 9
Current_Date = new Date(Current_Date.setHours(Current_Date.getHours() - 24)); // Feb 8
var Billing_Dates = []
while (Current_Date.valueOf() <= Date_end.valueOf()) {
Current_Date = new Date(Current_Date.setHours(Current_Date.getHours() + 24));
Billing_Dates.push(Current_Date);
Logger.log(Billing_Dates)
}
}
Simplified Output (including the status of the array after every push):
[Feb 09]
[Feb 10, Feb 10]
[Feb 10, Feb 11, Feb 11]
[Feb 10, Feb 11, Feb 12, Feb 12]
[Feb 10, Feb 11, Feb 12, Feb 13, Feb 13]
Image of the Exact Output (including the status of the array after every push)
When you do
Billing_Dates.push(Current_Date)
you are pushing the reference to the date, not the date itself. So on the next loop, you change the date and anything referencing it changes as well. That's why the last two dates in your array always appear the same. In this line
Current_Date = new Date(Current_Date.setHours(Current_Date.getHours() + 24));
You create a new reference by doing new Date(), which is why it's only modifying the last two elements in your array.
To fix, create a new reference when you store in the array :
Billing_Dates.push(new Date(Current_Date))
Instead of copying references of dates and modifying them in place, create a new one each time, for example:
const numDays = 5
const oneDayOffset = 24 * 3600 * 1000;
const dates = [];
const startDate = new Date();
for (let i=0; i < numDays; i++){
const newDate = new Date( startDate.getTime() + i * oneDayOffset );
dates.push(newDate.toString())
}
console.log(dates)
function makeDateArray(start = '2/9/2021',end = '2/13/2021') {
let da = [];
let sd = new Date(start);
let ed = new Date(end);
let n = 0;
do {
da.push(new Date(sd.getFullYear(), sd.getMonth(), sd.getDate() + n++));
} while (new Date(da[da.length - 1]).valueOf() < ed.valueOf());
let db=da.map((d)=>{return Utilities.formatDate(new Date(d),Session.getScriptTimeZone(),"MMM dd")});
Logger.log(db);
}
Execution log
12:28:30 PM Notice Execution started
12:28:30 PM Info [Feb 09, Feb 10, Feb 11, Feb 12, Feb 13]
12:28:30 PM Notice Execution completed
Example:
GMT Wednesday, January 20, 2016 12:00:01 AM = 1453248001 =>
2016.0533
Just this, accurate to the day:
Time.at(1453248001).then { |t| t.year + t.yday / 365.25 }
and a bit more cumbersome to be precise to the second:
Time.at(1453248001).then do |t|
beginning_of_year = Time.utc("#{t.year}-01-01")
seconds_in_year = Time.utc("#{t.year + 1}-01-01") - beg_of_year
num_seconds = t - beginning_of_year
t.year + num_seconds / seconds_in_year
end
Given time values in seconds, the decimal part of the year is given by:
(supplied_time - year_start_time) / seconds_in_year
E.g.
// Return decimal UTC year given a time value in seconds
// e.g. 1453248001 (2016-01-20T00:00:01Z) = 2016.0519125999292
function decimalYear(tv) {
let d = new Date(tv * 1e3);
let y = d.getUTCFullYear();
let start = Date.UTC(y, 0, 1); // Start of UTC year
let end = Date.UTC(y + 1, 0, 1); // Start of following UTC year
return y + (d - start) / (end - start);
}
// Time values in seconds
[Date.UTC(2016, 0, 1, 0, 0, 0)/1e3|0, // 2016-01-01T00:00:00Z
Date.UTC(2016, 0, 1, 0, 0, 1)/1e3|0, // 2016-01-01T00:00:01Z
Date.UTC(2016, 0,20, 0, 0, 1)/1e3|0, // 2016-01-20T00:00:01Z
Date.UTC(2016,11,31,23,59,59)/1e3|0, // 2016-12-31T23:59:59Z
Date.UTC(2017, 0, 1, 0, 0, 0)/1e3|0 // 2017-01-01T00:00:00Z
].forEach(tv => console.log(tv + ' => ' + decimalYear(tv)));
Using a general formula gives accurate results regardless of whether the time value is in a leap year or not.
The example in the OP is incorrect:
Example: GMT Wednesday, January 20, 2016 12:00:01 AM = 1453248001 => 2016.0533
All the following are seconds UTC:
Time value for 2016-01-12T00:00:01Z is 1453248001
Start of 2016 is 1451606400
End of 2016 (i.e. start of 2017) is 1483228800
(timeValue - startOfYear) รท (endOfYear - startOfYear) = 0.0519125999292
var today = new Date();
var endYear = new Date(1995, 11, 31, 23, 59, 59, 999); // Set day and month
endYear.setFullYear(today.getFullYear()); // Set year to this year
console.log("Version 1: end year full date is ", endYear);
var msPerDay = 24 * 60 * 60 * 1000; // Number of milliseconds per day
var daysLeft = (endYear.getTime() - today.getTime()) / msPerDay;
var daysLeft = Math.round(daysLeft); //returns days left in the year
console.log(daysLeft,endYear);
// when l write that code answer is 245.
var today = new Date();
var endYear = new Date(2021, 0, 0, 0, 0, 0, 0); // Set day and month
console.log("Version 2: end year full date is ", endYear);
var msPerDay = 24 * 60 * 60 * 1000; // Number of milliseconds per day
var daysLeft = (endYear.getTime() - today.getTime()) / msPerDay;
var daysLeft = Math.round(daysLeft); //returns days left in the year
console.log(daysLeft,endYear);
// but when l add only 1 ms then answer returns like 244. but how is it possible? where has 1 day gone?
That is the difference with the time you set.
To be clear,
first endYear will print Thu Dec 31 2020 23:59:59
second endYear will print Thu Dec 31 2020 00:00:00
That is the difference you see there.
I will post the complete out put I received on console here as well.
Thu Dec 31 2020 23:59:59 GMT+0530 (India Standard Time)
245.0131708912037
245
Thu Dec 31 2020 00:00:00 GMT+0530 (India Standard Time)
244.01317090277777
244
==================EDIT==================
new Date(2021, 0, 0, 0, 0, 0, 0) calculates this to Dec 31st because date is indexed from 1 and not zero. If that value is zero it computes it as the day before the 31st of December.
For example,
new Date(Date.UTC(2021, 1, 0, 0, 0, 0, 0)) will print out Sat Jan 31 2021 05:30:00 GMT+0530 (India Standard Time)
and
new Date(Date.UTC(2021, 1, -1, 0, 0, 0, 0)) will print out Sat Jan 30 2021 05:30:00 GMT+0530 (India Standard Time)
I need to determine whether I'm in the Spring, Summer or Autumn period of any given year, and display the a journal based on that. The periods are as follows:
Spring: 14th January - 6th May
Summer: 7th May - 7th October
Autumn: 8th October - 13th January
So today (7th February), I'm in the Spring period (14th January 2019 - 6th May 2019) and showing the Spring 2019 issue. However, let's say it's Christmas Day 2019. I'll be in Autumn period (8th October 2019 - 13th January 2020) so I'll be showing the Autumn 2019 issue, which means the next Spring and Summer issues will be in 2020.
I've been messing around with JS dates and moment objects to try and establish the current/next periods based on today, and I would post my code here but I'm almost sure it's all useless. It the change of year over the Autumn period which is tripping me up. Does anyone have any libraries or suggestions that might help? Or am I overthinking this?
This is a super simple solution, with no libraries. Works for your problem as is and for all future years, only if the dates are the same every year.
If you planned to have many more issues per year and run this multiple times constantly, then this could be rewritten differently.
// you can completely ignore autumn because if it's not spring or summer it will be Autumn.
// But I still put it to 2019 just in case you planned to use it with this method.
let issues = { "Spring": [new Date(2019, 0, 14), new Date(2019, 4, 6)],
"Summer": [new Date(2019, 4, 7), new Date(2019, 9, 7)],
"Autumn": [new Date(2019, 9, 8), new Date(2019, 0, 13)]
}
// today is the day we are trying to find the correct issue for.
// Any date can be put here, just setFullYear to 2019, 2019 is arbitrary
let today = new Date().setFullYear(2019);
// console.log the appropriate issue for today
if (issues.Summer[0] <= today && issues.Summer[1] >= today) {
console.log("Summer");
} else if (issues.Spring[0] <= today && issues.Spring[1] >= today) {
console.log("Spring");
} else {
console.log("Autumn");
}
Answer modified from here. Just pass in the current season object and today's date (which can be a simple var date = new Date()). There arent any libraries I know of that give you seasonal dates automatically. You'll have to add some kind of code that runs on a schedule or executes during a specific season each year to update or rebuild the date objects so that they have the correct year.
If you're looking for more complicated a way of doing this without having to update the dates check out this post
var spring = {};
spring.startDate = "02/01/2019"
spring.endDate = "02/09/2019"
var today = "02/07/2019"
function checkSeason(season, currentDate) {
console.log(season.startDate)
console.log(currentDate)
var d1 = season.startDate.split("/");
var d2 = season.endDate.split("/");
var c = currentDate.split("/");
var from = new Date(d1[2], parseInt(d1[1]) - 1, d1[0]); // -1 because months are from 0 to 11
var to = new Date(d2[2], parseInt(d2[1]) - 1, d2[0]);
var check = new Date(c[2], parseInt(c[1]) - 1, c[0]);
if (check > from && check < to) {
console.log("its in the season")
}
}
checkSeason(spring, today)
As Sam said, you can avoid the year rollover by just comparing the other seasons for the current year. If it's not one of the others, it must be the roll over one.
function getSeason(d) {
// Default to today's date
d = d || new Date();
// Zero time part for comparison
d.setHours(0,0,0,0);
// Use the current year for comparisons
var year = d.getFullYear();
// Default season if others fail
var season = 'Autumn';
// Data for seasons, use ECMAScript month numbering
var seasons = [
{name: 'Spring',
start: [0, 14], // Jan 14
end: [4, 6]}, // May 06
{name: 'Summer',
start: [4, 7], // May 07
end: [9, 7]} // Oct 07
];
// Set season
seasons.forEach(s => {
let sStart = new Date(year, ...s.start);
let sEnd = new Date(year, ...s.end);
if (d >= sStart && d <= sEnd) {
season = s.name;
}
})
return season;
}
console.log('Today is : ' + getSeason());
[new Date(2019,0, 1), // 1 Jan Autumn
new Date(2019,0,21), // 21 Jan Spring
new Date(2019,5,30) // 30 Jun Summer
].forEach(d => {
console.log(d.toDateString()+ ': ' + getSeason(d));
});
The code can be more concise using newer features:
function getSeason(d = new Date()) {
d.setHours(0,0,0,0);
let year = d.getFullYear();
let seasons = [
{name: 'Spring', start: [0, 14], end: [4, 6]},
{name: 'Summer', start: [4, 7], end: [9, 7]}
];
return (seasons.find(s => d >= new Date(year, ...s.start) && d <= new Date(year, ...s.end)) || {name:'Autumn'}).name;
}
console.log('Today is : ' + getSeason());
[new Date(2019,0, 1), // 1 Jan Autumn
new Date(2019,0,21), // 21 Jan Spring
new Date(2019,5,30) // 30 Jun Summer
].forEach(d => {
console.log(d.toDateString()+ ': ' + getSeason(d));
});