Invalid date issue using new Date() - javascript

I am passing timestamp to below function and it is returning me date string properly but when i am executing below line it is giving me error invalid date.
var postDate = new Date(this.ConvertServerDateToLocal(timestamp));
//postDate returns invalid date object.
ConvertServerDateToLocal: function(dateInput){
// EST - UTC offset: 4 hours
var offset = 4.0,
/*
- calculate the difference between the server EST date and UTC
- the value returned by the getTime method is the number of milliseconds since 1 January 1970 00:00:00 UTC.
- the time-zone offset is the difference, in minutes, between UTC and local time
- 60000 milliseconds = 60 seconds = 1 minute
*/
serverDate = new Date(dateInput),
utc = serverDate.getTime() - (serverDate.getTimezoneOffset() * 60000),
/*
- apply the offset between UTC and EST (4 hours)
- 3600000 milliseconds = 3600 seconds = 60 minutes = 1 hour
*/
clientDate = new Date(utc + (3600000 * offset));
return clientDate.toLocaleString();
}
Below is example timestamp i am passing to ConvertServerDateToLocal() function.
timestamp = "Nov 22, 2017 23:05:58" // Throwing invalid date after output
timestamp = "Nov 09, 2017 18:30:19" // Working properly

function ConvertServerDateToLocal(dateInput) {
// EST - UTC offset: 4 hours
dateInput = "Nov 09, 2017 18:30:19";
var offset = 4.0,
/*
- calculate the difference between the server EST date and UTC
- the value returned by the getTime method is the number of milliseconds since 1 January 1970 00:00:00 UTC.
- the time-zone offset is the difference, in minutes, between UTC and local time
- 60000 milliseconds = 60 seconds = 1 minute
*/
serverDate = new Date(dateInput.toString());
utc = serverDate.getTime() - (serverDate.getTimezoneOffset() * 60000);
/*
- apply the offset between UTC and EST (4 hours)
- 3600000 milliseconds = 3600 seconds = 60 minutes = 1 hour
*/
clientDate = new Date(utc + (3600000 * offset));
//return clientDate.toLocaleString();
alert(clientDate.toLocaleString());
}
Converting the input paramter to string worked for me. But I am not sure why one date worked and the other didn't work. If you found the answer, please post it here. I also use Dates a lot and they are always a pain.

Related

How to correctly calculate difference in days between 2 dates with DST change?

I have a task to get days difference between 2 dates. My solution is like here https://stackoverflow.com/a/543152/3917754 just I use Math.ceil instead of Math.round - cause 1 day and something is more than 1 day.
It was fine until I got dates between DST change. For example:
In my timezone DST change was on 30 Oct.
So when I'm trying to find days diff between dates 20 Oct and 10 Nov in result I get 23 instead of 22.
There are solution how to identify DST date but is it good solution to add/substract 1 day if date is/isn't dst?
function datediff(toDate, fromDate) {
const millisecondsPerDay = 1000 * 60 * 60 * 24; // milliseconds in day
fromDate.setHours(0, 0, 0, 0); // Start just after midnight
toDate.setHours(23, 59, 59, 999); // End just before midnight
const millisBetween = toDate.getTime() - fromDate.getTime();
var days = Math.ceil(millisBetween / millisecondsPerDay);
return days;
}
var startDate = new Date('2022-10-20');
var endDate = new Date('2022-11-10');
console.log('From date: ', startDate);
console.log('To date: ', endDate);
console.log(datediff(endDate, startDate));

British Summer Time with jQuery Datepicker (calculation lost 1 day)

I use Vue.js with jQuery Datepicker and see the issue with calculation of how many days are left to the selected date:
Calculation the difference in days:
getDifferenceInDays: function(date1, date2) {
const diffTime = date2.getTime() - date1.getTime(); //Math.abs(...);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return diffDays;
},
As a result I don't see 13 days left. Perhaps the issue related to the British Summer Time which ends on 27th October:
Could you suggest any idea how to fix this issue.
Many thanks!
You're right, this is caused by a Daylight Saving Time (DST) transition, specifically the end of DST in the UK on the 27th of October.
Dates, Times and Timezones are really tricky in JavaScript. The native Date object is very awkward to deal with when we're accessing different timezones.
I would suggest checking out a library that is better at this kind of thing: moment and moment-timezone are very good at handling DST changes correctly.
The reason you're getting the incorrect result is that you're looking at the difference between dates in the UTC timezone (since getTime() always returns the number of milliseconds since 1970-01-01 00:00 UTC (the Unix Epoch)).
The result (in your case) will be 13.04 (or 13 + 1/24) days since the UTC offset changes between the two dates (from UTC+01 to UTC+00).
For example, 12:00 on the 14th of October London Time is 11:00 UTC,
while 12:00 on the 27th of October London Time is 12:00 UTC. So the difference will be 313 hours, or 13.04 days.
Since you're calling Math.ceil, this will round up to 14, which is not correct.
This works when both dates are within the same UTC offset (e.g. both in summer, both in winter). But then they are either side of a DST change, you will get an incorrect result.
The code below will calculate the days between two dates in the specified timezone. You can pass a third argument of true to moment.diff to get the fractional days. (This will be 0 in this case).
If you don't wish to use another library such as moment, you can simply use Math.round to get the approximate difference in days. This will not be as robust, since if date2 is less than 12 hours ahead of date1 you'll get zero days difference.
As long as you're aware of this, it may suffice for your needs. I've added a getDifferenceInDaysRounding to show this.
const CURRENT_TIMEZONE = "Europe/London";
// Date 1 is 12:00, 14th October, London time
const date1 = moment.tz("2019-10-14T12:00:00", CURRENT_TIMEZONE).toDate();
// Date 2 is 12:00, 27th October, London time
const date2 = moment.tz("2019-10-27T12:00:00", CURRENT_TIMEZONE).toDate();
function getDifferenceInDaysOriginal (date1, date2) {
const diffTime = date2.getTime() - date1.getTime();
let diff1 = diffTime / (1000 * 60 * 60 * 24);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return diffDays;
}
// Use with caution.. this will not work in all cases!
function getDifferenceInDaysRounding (date1, date2) {
const diffTime = date2.getTime() - date1.getTime();
const diffDays = Math.round(diffTime / (1000 * 60 * 60 * 24));
return diffDays;
}
function getDifferenceInDaysTimezoneAware(date1, date2, timezone) {
// Ensure the dates are in the correct timezone.
const dateLocal1 = moment.tz(date1.getTime(), timezone);
const dateLocal2 = moment.tz(date2.getTime(), timezone);
// Pass false to return the integer number of days. NB, this will be 0 for less than 24 hours difference. Pass true to get the fractional days.
return dateLocal2.diff(dateLocal1, "days", false);
}
console.log("Original result:", getDifferenceInDaysOriginal(date1, date2));
console.log("Get difference (rounding):", getDifferenceInDaysRounding(date1, date2));
console.log("Timezone-aware result:", getDifferenceInDaysTimezoneAware(date1, date2, CURRENT_TIMEZONE));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://momentjs.com/downloads/moment-timezone-with-data-1970-2030.js"></script>

Rounding date by multiple weeks

It is easy to round dates to the start of the current week like so:
function roundWeek() {
var current = new Date();
var startOfWeek = current.getDate() - current.getDay();
console.log(new Date(current.setDate(startOfWeek)));
}
roundWeek();
This works fine when rounding by one week, but it gets a bit more complex when rounding by multiple weeks.
For instance, say I would like to round in three-week periods. I know this would require an epoch (such as new Date(0)) to be able to properly calculate the starting date of the three-week period, but this too causes an issue:
January 1, 1970 (which is new Date(0)) occured on a Thursday, so assuming I used it in the following manner, it would always calculate the start of the week to be on a Thursday:
function roundWeek(weeks) {
var current = new Date();
const WEEK_IN_MS = 60*60*24*7*1000; //sec * min * hr * day * ms
var index = Math.floor( (current.getTime() / (WEEK_IN_MS*weeks)) );
var startOfPeriod = new Date( index * WEEK_IN_MS*weeks );
console.log( startOfPeriod );
}
roundWeek(3);
How can this be modified so that it properly starts on a Sunday instead of a Thursday? Is there a better way of doing this? And most importantly: Would a leap year cause issues with this?
You need to decide whether you want the three-week period to start the Sunday before Jan 1, 1970 (12/28/69) or after. For example, which Sunday would Jan 14, 1970 round to? Then you can calculate the difference between Thursday and either the previous Sunday or next Sunday and add or subtract (depending on the decision you made) that to your rounded solution.
Here's a variation of you function that also takes a date as input for testing.
function roundWeek(weeks, d) {
var current = new Date(d);
var first_sunday = 60 * 60 * 24 * 4 * 1000 // seconds between Sunday and Thursday
const WEEK_IN_MS = 60 * 60 * 24 * 7 * 1000; // week in ms
var index = Math.floor((current.getTime() / (WEEK_IN_MS * weeks)));
console.log(`${weeks}-week periods from ${d.getMonth()+1}/${d.getDate()}/${d.getFullYear()} ${index}`)
var startOfPeriod = new Date(index * WEEK_IN_MS * weeks - first_sunday);
console.log("1st day of period:", startOfPeriod);
}
// round to three weeks starting Sunday before Jan 1 1970
roundWeek(3, new Date('January 2, 1970')); // Dec 28, 1968
roundWeek(3, new Date('January 14, 1970')); // Dec 28, 1968
roundWeek(3, new Date('January 22, 1970')); // next three weeks
roundWeek(3, new Date('May 16, 2018')); // since today. Sundaay May 6
Since leap years don't change how long a week is, they should be irrelevant.

How do I construct a javascript date using a 'day of the year (0 - 365)'? [duplicate]

I want to take a day of the year and convert to an actual date using the Date object. Example: day 257 of 1929, how can I go about doing this?
"I want to take a day of the year and convert to an actual date using the Date object."
After re-reading your question, it sounds like you have a year number, and an arbitrary day number (e.g. a number within 0..365 (or 366 for a leap year)), and you want to get a date from that.
For example:
dateFromDay(2010, 301); // "Thu Oct 28 2010", today ;)
dateFromDay(2010, 365); // "Fri Dec 31 2010"
If it's that, can be done easily:
function dateFromDay(year, day){
var date = new Date(year, 0); // initialize a date in `year-01-01`
return new Date(date.setDate(day)); // add the number of days
}
You could add also some validation, to ensure that the day number is withing the range of days in the year supplied.
The shortest possible way is to create a new date object with the given year, January as month and your day of the year as date:
const date = new Date(2017, 0, 365);
console.log(date.toLocaleDateString());
As for setDate the correct month gets calculated if the given date is larger than the month's length.
// You might need both parts of it-
Date.fromDayofYear= function(n, y){
if(!y) y= new Date().getFullYear();
var d= new Date(y, 0, 1);
return new Date(d.setMonth(0, n));
}
Date.prototype.dayofYear= function(){
var d= new Date(this.getFullYear(), 0, 0);
return Math.floor((this-d)/8.64e+7);
}
var d=new Date().dayofYear();
//
alert('day#'+d+' is '+Date.fromDayofYear(d).toLocaleDateString())
/* returned value: (String)
day#301 is Thursday, October 28, 2010
*/
Here is a function that takes a day number, and returns the date object
optionally, it takes a year in YYYY format for parameter 2. If you leave it off, it will default to current year.
var getDateFromDayNum = function(dayNum, year){
var date = new Date();
if(year){
date.setFullYear(year);
}
date.setMonth(0);
date.setDate(0);
var timeOfFirst = date.getTime(); // this is the time in milliseconds of 1/1/YYYY
var dayMilli = 1000 * 60 * 60 * 24;
var dayNumMilli = dayNum * dayMilli;
date.setTime(timeOfFirst + dayNumMilli);
return date;
}
OUTPUT
// OUTPUT OF DAY 232 of year 1995
var pastDate = getDateFromDayNum(232,1995)
console.log("PAST DATE: " , pastDate);
PAST DATE: Sun Aug 20 1995 09:47:18 GMT-0400 (EDT)
Here's my implementation, which supports fractional days. The concept is simple: get the unix timestamp of midnight on the first day of the year, then multiply the desired day by the number of milliseconds in a day.
/**
* Converts day of the year to a unix timestamp
* #param {Number} dayOfYear 1-365, with support for floats
* #param {Number} year (optional) 2 or 4 digit year representation. Defaults to
* current year.
* #return {Number} Unix timestamp (ms precision)
*/
function dayOfYearToTimestamp(dayOfYear, year) {
year = year || (new Date()).getFullYear();
var dayMS = 1000 * 60 * 60 * 24;
// Note the Z, forcing this to UTC time. Without this it would be a local time, which would have to be further adjusted to account for timezone.
var yearStart = new Date('1/1/' + year + ' 0:0:0 Z');
return yearStart + ((dayOfYear - 1) * dayMS);
}
// usage
// 2015-01-01T00:00:00.000Z
console.log(new Date(dayOfYearToTimestamp(1, 2015)));
// support for fractional day (for satellite TLE propagation, etc)
// 2015-06-29T12:19:03.437Z
console.log(new Date(dayOfYearToTimestamp(180.51323423, 2015)).toISOString);
If I understand your question correctly, you can do that from the Date constructor like this
new Date(year, month, day, hours, minutes, seconds, milliseconds)
All arguments as integers
You have a few options;
If you're using a standard format, you can do something like:
new Date(dateStr);
If you'd rather be safe about it, you could do:
var date, timestamp;
try {
timestamp = Date.parse(dateStr);
} catch(e) {}
if(timestamp)
date = new Date(timestamp);
or simply,
new Date(Date.parse(dateStr));
Or, if you have an arbitrary format, split the string/parse it into units, and do:
new Date(year, month - 1, day)
Example of the last:
var dateStr = '28/10/2010'; // uncommon US short date
var dateArr = dateStr.split('/');
var dateObj = new Date(dateArr[2], parseInt(dateArr[1]) - 1, dateArr[0]);
this also works ..
function to2(x) { return ("0"+x).slice(-2); }
function formatDate(d){
return d.getFullYear()+"-"+to2(d.getMonth()+1)+"-"+to2(d.getDate());
}
document.write(formatDate(new Date(2016,0,257)));
prints "2016-09-13"
which is correct as 2016 is a leaap year. (see calendars here: http://disc.sci.gsfc.nasa.gov/julian_calendar.html )
If you always want a UTC date:
function getDateFromDayOfYear (year, day) {
return new Date(Date.UTC(year, 0, day))
}
console.log(getDateFromDayOfYear(2020, 1)) // 2020-01-01T00:00:00.000Z
console.log(getDateFromDayOfYear(2020, 305)) // 2020-10-31T00:00:00.000Z
console.log(getDateFromDayOfYear(2020, 366)) // 2020-12-31T00:00:00.000Z

Calculate Date with start date and number of days with javascript

I am trying to calculate a date from a start date and number of days, so basicly add the number of days to a start date and get an end date. The issue is I get some strange results, but only on one date, I have been a few days now trying to figure this one out.
The function is:
CallculateDateFromDays = function(startDate, days) {
var policy_start_date_array = startDate.split("-");
var policy_start_date = new Date(policy_start_date_array[2], policy_start_date_array[1]-1, policy_start_date_array[0]);
var policy_start_date_add = new Date(policy_start_date.getTime() + ((days-1) * 24 * 60 * 60 * 1000));
var dateString = ("0" + (policy_start_date_add.getDate())).slice(-2) + "-" + ("0" + (policy_start_date_add.getMonth()+1)).slice(-2) + "-" + policy_start_date_add.getFullYear();
return dateString;}
The thing is it works until I use the date "28-10-2012" it gives me back the same date even if I add 2 days.
Any ideas, I am stumped.
Likely your local timezone changes because of the end of the daylight saving time.
> new Date(2012, 9, 28)
Sun Oct 28 2012 00:00:00 GMT+0200
> // 48 hours later:
> new Date(new Date(2012, 9, 28) + 2 * 24 * 60 * 60 * 1000)
Mon Oct 29 2012 23:00:00 GMT+0100
Always use the UTC methods!
BTW, adding days is much more easier with setDate, which also works around timezone issues:
function calculateDateFromDays(startDate, days) {
var datestrings = startDate.split("-"),
date = new Date(+datestrings[2], datestrings[1]-1, +datestrings[0]);
date.setDate(date.getDate() + days);
return [("0" + date.getDate()).slice(-2), ("0" + (date.getMonth()+1)).slice(-2), date.getFullYear()].join("-");
}
On October 28th the time changes from DST to "normal", so the day is not equal 24h. That may cause issues in your code.
Also why (days-1) * 24 * 60 * 60 * 1000? If you set days to 1 the whole expression evaluates to zero...
There's an easier way to achieve that :
http://jsfiddle.net/pjambet/wZEFe/2/
Use javascript date format:
How to format a JavaScript date
So you don't have to manually try to parse date strings.

Categories

Resources