How to find Days difference between two dates using javascript - javascript

I need to find days difference between two dates using javascript, here is my code
I have start date and end date
var diff = Math.floor((Date.parse(enddate) - Date.parse(startdate)) / 86400000);
Its calculating the difference from current time. I need to find the number of dates between given dates.
For example if i give input start date as 17-dec-2014 and 19-dec-2014 its displaying two days, but i need to calculate number of days 17,18 and 19. It should display number of days as three.
Any one help me please?

You can set the hours, minutes, seconds, and milliseconds to 0 before doing the comparison in order to ignore the time of day, e.g.:
var startdate = "2014-12-17";
var enddate = "2014-12-19";
var start = new Date(startdate);
start.setHours(0, 0, 0, 0); // Sets hours, minutes, seconds, and milliseconds
var end = new Date(enddate);
end.setHours(0, 0, 0, 0);
var diff = Math.round((end - start) / 86400000) + 1; // See note below re `+ 1`
snippet.log("diff = " + diff); // 3
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Two notes on that:
Math.round: This is here because if the timespan crosses a Daylight Savings Time boundary, the number will be off by a small fraction, but within the realm where rounding corrects it. Note that you must round, not truncate, floor, ceiling.
+ 1: The + 1 at the end of the diff = line is because your "difference" is unusual, because you're counting the start and end days inclusive. That's very odd, it would say that the difference in days from one Monday to the next was eight, not seven, because it would count the Monday on either end. But you said:
For example if i give input start date as 17-dec-2014 and 19-dec-2014 its displaying two days, but i need to calculate number of days 17,18 and 19.
...so you need the + 1. A normal difference between two dates wouldn't have it.
Example across DST boundaries (in many timezones):
var start, end, diff;
start = new Date(2014, 2, 1); // March 1st 2014
end = new Date(2014, 5, 1); // May 1st 2014
diff = ((end - start) / (1000 * 3600 * 24)) + 1;
// diff won't *quite* be 93, because of the change to DST
// (assuming a timezone where DST changes sometime in
// March, as in most parts of the U.S., UK, and Canada
snippet.log("diff = " + diff + " instead of 93");
snippet.log("rounded = " + Math.round(diff));
// Similarly, at the other end:
start = new Date(2014, 9, 1); // October 1st 2014
end = new Date(2014, 11, 1); // December 1st 2014
diff = ((end - start) / (1000 * 3600 * 24)) + 1;
// diff won't *quite* be 62, because of the change to DST
// (assuming a timezone where DST changes sometime in
// March, as in most parts of the U.S., UK, and Canada
snippet.log("diff = " + diff + " instead of 62");
snippet.log("rounded = " + Math.round(diff));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
This is the kind of thing that makes me turn to a library like MomentJS. Using MomentJS, it would be:
var diff = moment(enddate).diff(moment(startdate), 'days') + 1;
...where again the + 1 is because of your unusual definition of the difference between two dates.

Related

Given a date, how can I get the previous Monday in UTC format regardless of time zone?

I am given a unix timestamp like this: 1655402413 and am needing to find find the midnight of the Monday (in UTC/GMT format) of the same week, regardless of what day it is or what time zone. I then need to represent that Monday as a unix timestamp and return it. The function I have is as follows:
function findMonday(unixTimeStamp) {
let startDate = new Date(unixTimeStamp);
let startDay = startDate.getDay();
let diff = startDate.getDate() - startDay + (startDay === 0 ? -6 : 1);
let monday = new Date(startDate.setDate(diff));
monday.setHours(0, 0, 0, 0);
monday = new Date(monday).valueOf();
return monday;
}
That function almost works, but there are two problems, both related to the fact that the Date seems to always work with the user's current timezone:
If given a timestamp that evaluates to midnight on a Monday in UTC/GMT format, depending on the time zone of the user, it returns the Monday of the previous week (because startDate evaluates to the Sunday before the Monday), which is not good.
The monday that is returned is in local time, not UTC/GMT time.
This is driving me absolutely insane. Working with dates in JavaScript is a nightmare, and I would appreciate any direction you can give me.
Multiply the unix timestamp by 1000, and use the UTC methods like getUTCDate instead of getDate, setUTCHours instead of setHours etc..
Of course to return as unix time, just divide by 1000.
eg.
function findMonday(unixTimeStamp) {
let startDate = new Date(unixTimeStamp * 1000);
let startDay = startDate.getUTCDay();
let diff = startDate.getUTCDate() - startDay + (startDay === 0 ? -6 : 1);
let monday = new Date(startDate.setUTCDate(diff));
monday.setUTCHours(0, 0, 0, 0);
monday = new Date(monday).valueOf();
return monday;
}
const monday = findMonday(1655402413);
const unixMonday = Math.trunc(monday / 1000);
console.log('The Date: ' + new Date(monday).toISOString());
console.log('Unix time: ' + unixMonday);
As for Keith's answer but a little more concise. It returns seconds, not milliseconds. ;-)
// Given UNIX timestamp, return similar timestamp for
// previous UTC Monday at 00:00:00
let getLastUTCMonday = ts => {
let d = new Date(ts * 1e3);
d.setUTCDate(d.getUTCDate() - (d.getUTCDay() || 7) + 1);
return d.setUTCHours(0,0,0,0) / 1e3 | 0;
};
let ts = 1655402413;
let tsPriorMonday = getLastUTCMonday(ts)
console.log(
`Start date : ${new Date(ts*1e3).toUTCString()}\n` +
`Prior Monday: ${new Date(tsPriorMonday * 1e3).toUTCString()}`
);
In ECMA-262, offsets from the epoch (in milliseconds) are called "time values". A timestamp is anything that represents a time or date, so a time value is a timestamp. ;-)
Given that ECMAScript UTC days are always exactly 8.64e7 milliseconds long, you can work out the previous UTC Monday from today by some simple arithmetic.
The ECMAScript epoch was Thursday, 1 Jan 1970 00:00:00, so you can:
Subtract 4 UTC days worth of milliseconds (34.56e7) from the date to align with Monday instead of Thursday
Get the remainder of dividing that value by the number of milliseconds in 7 UTC days (7 * 8.64e7 or 60.48e7)
Subtract the remainder from the current date, which will return the previous Monday and also remove the time component
The above algorithm only works for dates after the epoch. Dates before then have time values are negative so add 3 days before getting the remainder, then subtract the remainder + 7 days (i.e. date - remainder - 7 days).
The following just does the post–epoch calculation:
let getPreviousUTCMonday = date => {
let weekRem = (date - 34.56e7) % 60.48e7;
return date - weekRem;
}
let d = new Date();
for (let i=0; i<12; i++) {
console.log(`${d.toUTCString()}\n` +
`${new Date(getPreviousUTCMonday(d)).toUTCString()}`);
d.setDate(d.getDate() + 1);
}

How to make operations with Dates/Hours in Javascript?

I have to subtract two hours passed by the user in the format 'HH: MM' and the result has to divide by the number of feeds on the day and set the exact hours that it should feed.
What the best way to get the difference between 2 hours and divide by the number of meals and get the correct interval to save?
In most browsers, Dates support the subtraction operator, which will return the number of milliseconds between them. Alternatively, you can get a timestamp (the number of milliseconds since the Unix Epoch) by calling .getTime(). This second option may be a bit safer and have broader support, though I haven't found an authoritative source or document to corroborate.
The result will be positive if the Date on the left is after the date on the right and negative if it is before. If you want the difference represented as a positive number either way then you can use Math.abs().
var x = new Date(2019, 0, 1);
var y = new Date(2019, 0, 1, 5, 45);
// NOTE: You haven't specified how to handle "negative" differences
var diff = Math.abs(y.getTime() - x.getTime());
// From here it's simple arithmetic:
var hours = Math.floor(diff / 3600000);
var minutes = Math.floor((diff % 3600000) / 60000);
// NOTE: Differences greater than 99:59 will be truncated!
console.log( ("00" + hours).slice(-2) + ":" + ("00" + minutes).slice(-2) )
As for the rest of your question:
the result has to divide by the number of feeds on the day and set the exact hours that it should feed.
I have no idea what this means. Hopefully the date logic is enough for you to get started.
You simply cannot pass hours, you have to pass Date to know which one is larger than other.
function diff_hours(dt2, dt1)
{
var diff =(dt2.getTime() - dt1.getTime()) / 1000;
diff /= (60 * 60);
return Math.abs(Math.round(diff));
}
var amount_of_meal = 8;
dt1 = new Date(2014,10,2);
dt2 = new Date(2014,10,3);
var result = (diff_hours(dt1, dt2))/amount_of_meal;
dt1 = new Date("October 13, 2014 08:11:00");
dt2 = new Date("October 13, 2014 11:13:00");
console.log(diff_hours(dt1, dt2));
If you prefer to use a library, you can use momentJS => https://momentjs.com/docs/
But I dont think you need to.
If you want to subtract two hours from a certain date you can do it like this /
var x = new Date();
x = Date.parse(x);
x = x - 7200000;
x = new Date(x);
console.log(x);

JS/PHP, time of date

i would like to ask, if someone know to to make in JS or PHP time of date.
Or how long we're together, like 70 days or 2 month and some days, and all day add 1 more day. I have something whats work, but on begging of that time is - .
I spent a lot time with making something what should work. But nothing.
There is that code with that -
<script charset="UTF-8">
function daysTill() {
var day= 8
var month= 12
var year= 2016
var event= "relationship with my ♥"
var end = "days of"
var daystocount=new Date(year, month -1, day)
today=new Date()
if (today.getMonth()==month && today.getDate()>day)
daystocount.setFullYear(daystocount.getFullYear())
var oneday=1000*60*60*24
var write = (Math.ceil((daystocount.getTime()-today.getTime())/(oneday)))
document.write('<strong>'+write +'</strong> '+end+' '+event)
}
daysTill();
</script>
if someone know, please help me. Thanks ♥
The getTime() method returns the time in milliseconds so to convert it to days you divide that by 86400000 (1000 for seconds * 60 for minutes * 60 for hours * 24 for days):
var relationship = new Date("2016/12/08");
var today = new Date();
var days = Math.ceil((today.getTime() - relationship.getTime()) / 86400000);
document.write(days + " days have pass since the start of the relationship.");
Try to use "JavaScript date maths"
// new Date(year, month (0-11!), day, hours, minutes, seconds, milliseconds);
var dateFuture = new Date(2017, 3, 1, 9, 0, 0, 0);
var dateLongAgo = new Date(2001, 8, 11, 8, 46, 0, 0);
var dateNow = new Date();
//86400000 millis per day
//floor --> all unter a full day shall be 'no day'
var daysSince = Math.floor((dateNow-dateLongAgo)/86400000);
var daysUntil = Math.floor((dateFuture-dateNow)/86400000);
console.log("long ago\t", dateLongAgo);
console.log("now is\t\t",dateNow);
console.log("then\t\t",dateFuture);
console.log("days since\t",daysSince);
console.log("days until\t", daysUntil);
If you don't mind using external libraries, Carbon is a nice tool extending DateTime
http://carbon.nesbot.com/docs/
It returns many kinds very nicely formatted dates -- months, days, hours etc included.

UTC time for css

I have this script working it gives me the UTC time but it goes over 24!
example
sydney time 13 + (-11) = 2 | Los Angeles time 19 +(7) = 26
this 26 show be 2! because 24 is maximum
var now = new Date();
var utc = (now.getHours() + (now.getTimezoneOffset() / 60));
Use
now.getUTCHours()
For reference see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCHours
You don't need to, and shouldn't, calculate this. getUTCHours gets you UTC time.
That said, if you still want to do the calculation / make your life harder:
var now = new Date();
var utc = (now.getHours() + (now.getTimezoneOffset() / 60)) % 24;
The % 24 is necessary to account for situations (like you encountered) where the conversion yields a number outside 0-23.

Converting Excel Date Serial Number to Date using Javascript

I have the following javascript code that convert date (string) to the Date Serial Number used in Microsoft Excel:
function JSDateToExcelDate(inDate) {
var returnDateTime = 25569.0 + ((inDate.getTime() - (inDate.getTimezoneOffset() * 60 * 1000)) / (1000 * 60 * 60 * 24));
return returnDateTime.toString().substr(0,5);
}
So, how do I do the reverse? (Meaning that a Javascript code that convert the Date Serial Number used in Microsoft Excel to a date string?
Try this:
function ExcelDateToJSDate(serial) {
var utc_days = Math.floor(serial - 25569);
var utc_value = utc_days * 86400;
var date_info = new Date(utc_value * 1000);
var fractional_day = serial - Math.floor(serial) + 0.0000001;
var total_seconds = Math.floor(86400 * fractional_day);
var seconds = total_seconds % 60;
total_seconds -= seconds;
var hours = Math.floor(total_seconds / (60 * 60));
var minutes = Math.floor(total_seconds / 60) % 60;
return new Date(date_info.getFullYear(), date_info.getMonth(), date_info.getDate(), hours, minutes, seconds);
}
Custom made for you :)
I made a one-liner for you:
function ExcelDateToJSDate(date) {
return new Date(Math.round((date - 25569)*86400*1000));
}
The Short Answer
new Date(Date.UTC(0, 0, excelSerialDate - 1));
Why This Works
I really liked the answers by #leggett and #SteveR, and while they mostly work, I wanted to dig a bit deeper to understand how Date.UTC() worked.
Note: There could be issues with timezone offsets, especially for older dates (pre-1970). See Browsers, time zones, Chrome 67 Error (historic timezone changes) so I'd like to stay in UTC and not rely on any shifting of hours if at all possible.
Excel dates are integers based on Jan 1st, 1900 (on PC. on MAC it is based from Jan 1st, 1904). Let's assume we are on a PC.
1900-01-01 is 1.0
1901-01-01 is 367.0, +366 days (Excel incorrectly treats 1900 as a leap year)
1902-01-01 is 732.0, +365 days (as expected)
Dates in JS are based on Jan 1st 1970 UTC. If we use Date.UTC(year, month, ?day, ?hour, ?minutes, ?seconds) it will return the number of milliseconds since that base time, in UTC. It has some interesting functionality which we can use to our benefit.
All normal ranges of the parameters of Date.UTC() are 0 based except day. It does accept numbers outside those ranges and converts the input to over or underflow the other parameters.
Date.UTC(1970, 0, 1, 0, 0, 0, 0) is 0ms
Date.UTC(1970, 0, 1, 0, 0, 0, 1) is 1ms
Date.UTC(1970, 0, 1, 0, 0, 1, 0) is 1000ms
It can do dates earlier than 1970-01-01 too. Here, we decrement the day from 0 to 1, and increase the hours, minutes, seconds and milliseconds.
Date.UTC(1970, 0, 0, 23, 59, 59, 999) is -1ms
It's even smart enough to convert years in the range 0-99 to 1900-1999
Date.UTC(70, 0, 0, 23, 59, 59, 999) is -1ms
Now, how do we represent 1900-01-01? To easier view the output in terms of a date I like to do
new Date(Date.UTC(1970, 0, 1, 0, 0, 0, 0)).toISOString() gives "1970-01-01T00:00:00.000Z"
new Date(Date.UTC(0, 0, 1, 0, 0, 0, 0)).toISOString() gives "1900-01-01T00:00:00.000Z"
Now we have to deal with timezones. Excel doesn't have a concept of a timezone in its date representation, but JS does. The easiest way to work this out, IMHO, is to consider all Excel dates entered as UTC (if you can).
Start with an Excel date of 732.0
new Date(Date.UTC(0, 0, 732, 0, 0, 0, 0)).toISOString() gives "1902-01-02T00:00:00.000Z"
which we know is off by 1 day because of the leap year issue mentioned above. We must decrement the day parameter by 1.
new Date(Date.UTC(0, 0, 732 - 1, 0, 0, 0, 0)) gives "1902-01-01T00:00:00.000Z"
It is important to note that if we construct a date using the new Date(year, month, day) constructor, the parameters use your local timezone. I am in the PT (UTC-7/UTC-8) timezone and I get
new Date(1902, 0, 1).toISOString() gives me "1902-01-01T08:00:00.000Z"
For my unit tests, I use
new Date(Date.UTC(1902, 0, 1)).toISOString() gives "1902-01-01T00:00:00.000Z"
A Typescript function to convert an excel serial date to a js date is
public static SerialDateToJSDate(excelSerialDate: number): Date {
return new Date(Date.UTC(0, 0, excelSerialDate - 1));
}
And to extract the UTC date to use
public static SerialDateToISODateString(excelSerialDate: number): string {
return this.SerialDateToJSDate(excelSerialDate).toISOString().split('T')[0];
}
Specs:
1) https://support.office.com/en-gb/article/date-function-e36c0c8c-4104-49da-ab83-82328b832349
Excel stores dates as sequential serial numbers so that they can be
used in calculations. January 1, 1900 is serial number 1, and January
1, 2008 is serial number 39448 because it is 39,447 days after January
1, 1900.
2) But also: https://support.microsoft.com/en-us/help/214326/excel-incorrectly-assumes-that-the-year-1900-is-a-leap-year
When Microsoft Multiplan and Microsoft Excel were released, they also
assumed that 1900 was a leap year. This assumption allowed Microsoft
Multiplan and Microsoft Excel to use the same serial date system used
by Lotus 1-2-3 and provide greater compatibility with Lotus 1-2-3.
Treating 1900 as a leap year also made it easier for users to move
worksheets from one program to the other.
3) https://www.ecma-international.org/ecma-262/9.0/index.html#sec-time-values-and-time-range
Time is measured in ECMAScript in milliseconds since 01 January, 1970
UTC. In time values leap seconds are ignored. It is assumed that there
are exactly 86,400,000 milliseconds per day.
4) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Unix_timestamp
new Date(value)
An integer value representing the number of milliseconds since
January 1, 1970, 00:00:00 UTC (the Unix epoch), with leap seconds
ignored. Keep in mind that most Unix Timestamp functions are only
accurate to the nearest second.
Putting it together:
function xlSerialToJsDate(xlSerial){
// milliseconds since 1899-31-12T00:00:00Z, corresponds to xl serial 0.
var xlSerialOffset = -2209075200000;
var elapsedDays;
// each serial up to 60 corresponds to a valid calendar date.
// serial 60 is 1900-02-29. This date does not exist on the calendar.
// we choose to interpret serial 60 (as well as 61) both as 1900-03-01
// so, if the serial is 61 or over, we have to subtract 1.
if (xlSerial < 61) {
elapsedDays = xlSerial;
}
else {
elapsedDays = xlSerial - 1;
}
// javascript dates ignore leap seconds
// each day corresponds to a fixed number of milliseconds:
// 24 hrs * 60 mins * 60 s * 1000 ms
var millisPerDay = 86400000;
var jsTimestamp = xlSerialOffset + elapsedDays * millisPerDay;
return new Date(jsTimestamp);
}
As one-liner:
function xlSerialToJsDate(xlSerial){
return new Date(-2209075200000 + (xlSerial - (xlSerial < 61 ? 0 : 1)) * 86400000);
}
No need to do any math to get it down to one line.
// serialDate is whole number of days since Dec 30, 1899
// offsetUTC is -(24 - your timezone offset)
function SerialDateToJSDate(serialDate, offsetUTC) {
return new Date(Date.UTC(0, 0, serialDate, offsetUTC));
}
I'm in PST which is UTC-0700 so I used offsetUTC = -17 to get 00:00 as the time (24 - 7 = 17).
This is also useful if you are reading dates out of Google Sheets in serial format. The documentation suggests that the serial can have a decimal to express part of a day:
Instructs date, time, datetime, and duration fields to be output as doubles in "serial number" format, as popularized by Lotus 1-2-3. The whole number portion of the value (left of the decimal) counts the days since December 30th 1899. The fractional portion (right of the decimal) counts the time as a fraction of the day. For example, January 1st 1900 at noon would be 2.5, 2 because it's 2 days after December 30st 1899, and .5 because noon is half a day. February 1st 1900 at 3pm would be 33.625. This correctly treats the year 1900 as not a leap year.
So, if you want to support a serial number with a decimal, you'd need to separate it out.
function SerialDateToJSDate(serialDate) {
var days = Math.floor(serialDate);
var hours = Math.floor((serialDate % 1) * 24);
var minutes = Math.floor((((serialDate % 1) * 24) - hours) * 60)
return new Date(Date.UTC(0, 0, serialDate, hours-17, minutes));
}
I really liked Gil's answer for it's simplicity, but it lacked the timezone offset. So, here it is:
function date2ms(d) {
let date = new Date(Math.round((d - 25569) * 864e5));
date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
return date;
}
Although I stumbled onto this discussion years after it began, I may have a simpler solution to the original question -- fwiw, here is the way I ended up doing the conversion from Excel "days since 1899-12-30" to the JS Date I needed:
var exdate = 33970; // represents Jan 1, 1993
var e0date = new Date(0); // epoch "zero" date
var offset = e0date.getTimezoneOffset(); // tz offset in min
// calculate Excel xxx days later, with local tz offset
var jsdate = new Date(0, 0, exdate-1, 0, -offset, 0);
jsdate.toJSON() => '1993-01-01T00:00:00.000Z'
Essentially, it just builds a new Date object that is calculated by adding the # of Excel days (1-based), and then adjusting the minutes by the negative local timezone offset.
So, there I was, having the same problem, then some solutions bumped up but started to have troubles with the Locale, Time Zones, etc, but in the end was able to add the precision needed
toDate(serialDate, time = false) {
let locale = navigator.language;
let offset = new Date(0).getTimezoneOffset();
let date = new Date(0, 0, serialDate, 0, -offset, 0);
if (time) {
return serialDate.toLocaleTimeString(locale)
}
return serialDate.toLocaleDateString(locale)
}
The function's 'time' argument chooses between displaying the entire date or just the date's time
Thanks for #silkfire's solution!
After my verification. I found that when you're in the Eastern Hemisphere, #silkfire has the right answer; The western hemisphere is the opposite.
So, to deal with the time zone, see below:
function ExcelDateToJSDate(serial) {
// Deal with time zone
var step = new Date().getTimezoneOffset() <= 0 ? 25567 + 2 : 25567 + 1;
var utc_days = Math.floor(serial - step);
var utc_value = utc_days * 86400;
var date_info = new Date(utc_value * 1000);
var fractional_day = serial - Math.floor(serial) + 0.0000001;
var total_seconds = Math.floor(86400 * fractional_day);
var seconds = total_seconds % 60;
total_seconds -= seconds;
var hours = Math.floor(total_seconds / (60 * 60));
var minutes = Math.floor(total_seconds / 60) % 60;
return new Date(date_info.getFullYear(), date_info.getMonth(), date_info.getDate(), hours, minutes, seconds);
}
// Parses an Excel Date ("serial") into a
// corresponding javascript Date in UTC+0 timezone.
//
// Doesn't account for leap seconds.
// Therefore is not 100% correct.
// But will do, I guess, since we're
// not doing rocket science here.
//
// https://www.pcworld.com/article/3063622/software/mastering-excel-date-time-serial-numbers-networkdays-datevalue-and-more.html
// "If you need to calculate dates in your spreadsheets,
// Excel uses its own unique system, which it calls Serial Numbers".
//
lib.parseExcelDate = function (excelSerialDate) {
// "Excel serial date" is just
// the count of days since `01/01/1900`
// (seems that it may be even fractional).
//
// The count of days elapsed
// since `01/01/1900` (Excel epoch)
// till `01/01/1970` (Unix epoch).
// Accounts for leap years
// (19 of them, yielding 19 extra days).
const daysBeforeUnixEpoch = 70 * 365 + 19;
// An hour, approximately, because a minute
// may be longer than 60 seconds, see "leap seconds".
const hour = 60 * 60 * 1000;
// "In the 1900 system, the serial number 1 represents January 1, 1900, 12:00:00 a.m.
// while the number 0 represents the fictitious date January 0, 1900".
// These extra 12 hours are a hack to make things
// a little bit less weird when rendering parsed dates.
// E.g. if a date `Jan 1st, 2017` gets parsed as
// `Jan 1st, 2017, 00:00 UTC` then when displayed in the US
// it would show up as `Dec 31st, 2016, 19:00 UTC-05` (Austin, Texas).
// That would be weird for a website user.
// Therefore this extra 12-hour padding is added
// to compensate for the most weird cases like this
// (doesn't solve all of them, but most of them).
// And if you ask what about -12/+12 border then
// the answer is people there are already accustomed
// to the weird time behaviour when their neighbours
// may have completely different date than they do.
//
// `Math.round()` rounds all time fractions
// smaller than a millisecond (e.g. nanoseconds)
// but it's unlikely that an Excel serial date
// is gonna contain even seconds.
//
return new Date(Math.round((excelSerialDate - daysBeforeUnixEpoch) * 24 * hour) + 12 * hour);
};
dart implementation of #silkfire answer
DateTime getDateFromSerialDay(double serial) {
final utc_days = (serial - 25569).floor();
final utc_value = utc_days * 86400;
final date_info = DateTime.fromMillisecondsSinceEpoch(utc_value * 1000);
final fractional_day = serial - utc_days + 0.0000001;
var total_seconds = (86400 * fractional_day).floor();
var seconds = total_seconds % 60;
total_seconds -= seconds;
var hours = (total_seconds / (60 * 60) % 24).floor();
var minutes = ((total_seconds / 60) % 60).floor();
return DateTime(date_info.year, date_info.month, date_info.day, hours,
minutes, seconds);
}
It's an old thread but hopefully I can save you the time I used readying around to write this npm package:
$ npm install js-excel-date-convert
Package Usage:
const toExcelDate = require('js-excel-date-convert').toExcelDate;
const fromExcelDate = require('js-excel-date-convert').fromExcelDate;
const jul = new Date('jul 5 1998');
toExcelDate(jul); // 35981 (1900 date system)
fromExcelDate(35981); // "Sun, 05 Jul 1998 00:00:00 GMT"
You can verify these results with the example at https://learn.microsoft.com/en-us/office/troubleshoot/excel/1900-and-1904-date-system
The Code:
function fromExcelDate (excelDate, date1904) {
const daysIn4Years = 1461;
const daysIn70years = Math.round(25567.5 + 1); // +1 because of the leap-year bug
const daysFrom1900 = excelDate + (date1904 ? daysIn4Years + 1 : 0);
const daysFrom1970 = daysFrom1900 - daysIn70years;
const secondsFrom1970 = daysFrom1970 * (3600 * 24);
const utc = new Date(secondsFrom1970 * 1000);
return !isNaN(utc) ? utc : null;
}
function toExcelDate (date, date1904) {
if (isNaN(date)) return null;
const daysIn4Years = 1461;
const daysIn70years = Math.round(25567.5 + 1); // +1 because of the leap-year bug
const daysFrom1970 = date.getTime() / 1000 / 3600 / 24;
const daysFrom1900 = daysFrom1970 + daysIn70years;
const daysFrom1904Jan2nd = daysFrom1900 - daysIn4Years - 1;
return Math.round(date1904 ? daysFrom1904Jan2nd : daysFrom1900);
}
If you want to know how this works check: https://bettersolutions.com/excel/dates-times/1904-date-system.htm

Categories