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
Related
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);
}
I'm making a Discord bot that I want to have a reward that you can claim once per day, and if you've already claimed it, it tells you how much time left. I've made the function that converts milliseconds into a readable format, but somehow using Date objects isn't working. Here is my code to get the timestamp in ms of the next claim time:
const nextdate = new Date(oldms + 86400000); // oldms is the miliseconds timestamp of the last claim time, this adds 24 hours to it.
// The next two lines are to set it to 00:00:00 so it can show the time until properly.
const regex = new RegExp(" ..:..:.. GMT");
const realnextdate = new Date(nextdate.toUTCString().replace(regex, ""));
return realnextdate.getTime();
But when I run it, the time is always the day before the next claim, so the remaining time is negative. Can anyone tell me how I can get the actual timestamp of the next midnight?
Edit 1: My server is in UTC + 2 timezone, if that changes anything. (Optimally, it should not.)
Adding one day is not as simple as adding 24 hours where daylight saving is observed, see How can I add 1 day to current date?
It's unclear to me whether you want UTC or local midnight, but here is how to get both. For UTC midnight, create a date for 24:00:00 UTC and subtract the current date and time from it.
For local midnight, subtract the date from midnight on the same day. In both cases, the milliseconds can then be formatted as H:mm:ss.sss or whatever suits.
The difference between the time to local midnight and UTC midnight will be equivalent to the current timezone offset.
// Format ms as H:mm:ss.sss
function msToHMS(ms) {
let h = ms / 3.6e6 | 0;
let m = (ms % 3.6e6) / 6e4 | 0;
let s = (ms % 6e4) / 1e3 | 0;
let ss = (ms % 1e3);
return `${h}:${('' + m).padStart(2, '0')}:${('' + s).padStart(2, '0')}.${(''+ss).padStart(3, '0')}`;
}
// Return time to UTC midnight as H:mm:ss.sss
function timeToUTCMidnight(d = new Date()) {
return msToHMS(new Date(d).setUTCHours(24,0,0,0) - d);
}
// Return time to local midngith as H:mm:ss.sss
function timeTolocalMidnight(d = new Date()) {
return msToHMS(new Date(d).setHours(24,0,0,0) - d);
}
console.log('To UTC midnight : ' + timeToUTCMidnight().padStart(12));
console.log('To local midnight: ' + timeTolocalMidnight().padStart(12));
Get time till next midnight
Algorithm
Get next midnight time as a js date object
Get the current time
Subtract, to get remaining time
To get the next midnight, use
function getNextMidnightTime() {
var midnight = new Date()
midnight.setHours(24);
midnight.setMinutes(0);
midnight.setSeconds(0);
midnight.setMilliseconds(0);
return midnight.getTime()
}
For which to get the time remaining till midnight,
function getTimeToMidnightFromNowInMS() {
return getNextMidnight() - new Date().getTime()
}
To test
console.log(getTimeToMidnightFromNowInMS())
You can get the time of the start of the next day and then subtract the current time:
function msTillNextUtcDay() {
const msInDay = 86400000; // 24 * 60 * 60 * 1000
const date = Date.now() // time since midnight on January 1, 1970, UTC (ecmascript epoch)
const msNextDay = Math.ceil(date/msInDay) * msInDay; //gets the time of in ms of the start of the next utc day in ecmascript epoch "format"
return msNextDay - date; //Subtracts current time from start of next day
}
You can use DateInstance.getTimezoneOffset() to get the minutes difference from the Client to UTC. Set your minutes plus the offset, after setting everything else to zero, then DateInstance.getTime() and subtract Date.now().
function msToUTCMidnight(){
const d = new Date, z = d.getTimezoneOffset();
d.setDate(d.getDate()+1); d.setHours(0); d.setSeconds(0);
d.setMilliseconds(0); d.setMinutes(0+z);
return d.getTime()-Date.now();
}
let result = msToUTCMidnight();
console.log(result);
// show Client time at midnight UTC
console.log(new Date(Date.now()+result).toString());
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);
I would like to get the time of an ISO8601 string in the specified timezone.
However, whenever I grab the moment object of the ISO8601 string, it converts everything to my machine's local time.
E.g. when I do moment("2015-09-15T07:55+02:00").hours(), it returns 1 since it converted it to 2015-09-15T01:55:00-04:00".
How do I make it so that it returns 7 for hours?
I think this will help:
http://momentjs.com/docs/#/parsing/special-formats/
moment("2010-01-01T05:06:07", moment.ISO_8601);
not sure about moment, but here's my converter for the eastern time zone, if it helps...
getServerDate: function(dateValue) {
var dateJan;
var dateJul;
var timezoneOffset;
// Get dates for January and July
dateJan = new Date(dateValue.getFullYear(), 0, 1);
dateJul = new Date(dateValue.getFullYear(), 6, 1);
// Get timezone offset
timezoneOffset = Math.max(dateJan.getTimezoneOffset(), dateJul.getTimezoneOffset());
// Check if daylight savings
if (dateValue.getTimezoneOffset() < timezoneOffset) {
// Adjust date by 4 hours
dateValue = new Date(dateValue.getTime() + ((1 * 60 * 60 * 1000) * 4));
} else {
// Adjust date by 5 hours
dateValue = new Date(dateValue.getTime() + ((1 * 60 * 60 * 1000) * 5));
}
return dateValue;
},
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.