I am trying to plot an array of values on a line plot. The values each have a date/time stamp.
So an example data point is:
aPoint = { 'label': 201401082015, //so this corresponds to 2014, Jan 08th, at 10:15PM
'data' : 1234
};
How do I convert label into a form that nvd3 can recognise as a date/time? By not changing the form of label, incorrect spacing between data points will occur (due to 60 minutes in 1 hour, 24 hours in 1 day and not 100).
To elaborate, if an event occurs at 23:00 hrs (11pm), and another at 01:00 hrs (1am) the following day, then in reality these events are 2 hours apart. Incorrectly however, they will be plotted as if they are 78 hours (101-23=78) apart due to hours in a day not being base 10.
How do I convert label into a form that nvd3 can recognise as a date/time?
How do I convert label into a form that nvd3 can recognize as a
date/time?
Like this:
function labelToMs(label){
var parts = label.toString().match(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})$/);
var partsToInt = parts.slice(0,5).map(function(s){return parseInt(s)});
var date = new Date(partsToInt[0], partsToInt[1]-1, partsToInt[2], partsToInt[3], partsToInt[4]);
return date.getTime();
}
This function will return a number that won't have that issue, because it will be the number of milliseconds since 1 January 1970 00:00:00 UTC.
Also, if you have an Array of points and you want to convert it to an Array with the label as the number of MS, you could do it like this:
var yourArrayOfPoints = yourArrayOfPoints.map(function(point){
point.label = labelToMs(point.label);
return point;
});
Related
I have an app where a user can select two dates (a from date and a to date) and the time between the dates should not exceed 4 months. A user can select the day, month and year for each date. Is there some kind of logic I could use to achieve this, so that an error is returned if the date range is over 4 months. Each input as an integer. For example, a start date of March 31st 2019 would be: from_date_day = 31 from_date_month = 3 and from_date_year = 2019
For example, I something like this would kind of work:
((Math.abs($('#to_date_month').val() - $('#from_date_month').val()) > 2) && $('#from_date_day').val() <= $('#to_date_day').val()
return "error"
The problem with this code is that it doesn't work when the dates straddle two different years. I'm using coffeescript, but a solution in jquery or js would also work.
I'd recommend creating two Javascript Date objects of those two dates. This can be done by feeding the year, the month and finally the day to the constructor of the Date object.
e.g.
var startDate = new Date(2019, 1, 16); // January the 16th
var endDate = new Date(2019, 3, 30); // March the 30th
Using the .getTime() function of the Date object you can get the number of milliseconds passed since 1.1.1970. If you calculate the difference between those two numbers, wrap it inside Math.abs() and divide that number by 1000, 60, 60 and finally 24 you get the number of days. If this number is bigger than ~120, the range is more than four months.
console.log(Math.abs(startDate.getTime() - endDate.getTime()) / 1000/60/60/24);
In your use case the Date object could be set like this:
var startDate = new Date(parseInt($('#from_date_year').val()), parseInt($('#from_date_month').val()), parseInt($('#from_date_day').val()));
I have an interesting result from the javascript in an Acrobat PDF Form
I have a series of date form fields. The first field is for user entry and the remaining fields are calculated by javascript, each field incremented by one day.
The code is:
var strStart = this.getField("userField").value;
if(strStart.length > 0) {
var dateStart = util.scand("dd/mm/yy",strStart);
var dateStartMilli = dateStart.getTime();
var oneDay = 24 * 60 * 60 * 1000 * 1; // number of milliseconds in one day
var dateMilli = dateStartMilli + oneDay;
var date = new Date(dateMilli);
event.value = util.printd("dd/mm/yy",date);
} else { event.value = "" }
The issue is if I input 05/04/15 in to the user field the result is 05/04/15 (same, wrong) while any other date of the year correctly increments by one day (ie 25/10/15 gives 26/10/15, 14/2/15 gives 15/2/15 etc)
The same error occurs on the 3rd of April 2016, 2nd of April 2017, etc (ie each year)
I have a fortnight (14) of these incrementing fields, each incrementing the date from the previous calculated field with the same javascript as above ("userField" is changed to date2, date3, date4 etc). What is very strange is that the next field that increments off the second of the two 05/04/15 correctly returns 06/04/15 and there isn't an issue after that.
Does anyone know why this might be?!
That doesn't happen on my browser's JavaScript engine and/or in my locale, so it must be an Acrobat thing or that date may be special in your locale (e.g., DST).
In any case, that's not the correct way to add one day to a JavaScript date, not least because some days have more than that many milliseconds and some have less (transitioning to and from DST).
The correct way is to use getDate and setDate:
var strStart = this.getField("userField").value;
if(strStart.length > 0) {
var dateStart = util.scand("dd/mm/yy",strStart);
dateStart.setDate(dateStart.getDate() + 1); // Add one day
event.value = util.printd("dd/mm/yy",dateStart);
} else { event.value = "" }
setDate is smart enough to handle it if you go past the end of the month (per specification).
If it's DST-related, the above will fix it. If it's some weird Acrobat thing, perhaps it will work around it. Either way, it's how this should be done.
Let me guess, that's the day daylight savings starts in your locale? 24 hours after midnight is not always the next day, because some days have 25 hours.
Approaches that come to my head:
manipulate the day. (This is easy if Acrobat allows dates like the 32nd of January, because oyu can just increment the day. Otherwise, maybe don't bother because leap years aren't much better than DST.)
don't start from midnight. If you never use the hour and minute within the day, don't pin your day at the strike of midnight, but at, say, 3am. After a change in DST status, later days in your fortnight might register as 2am or 4am, but as long as you're only using the day…
Given a start date, and a number of days, I need to display the end date = start date + number of days.
So I did something like this:
var endDate=new Date(startDate.getTime()+ONE_DAY);
Everything works fine, except that for 25 and 26 October gives one day less.
Ex.:
2014-01-01 + 2 days = 2014-01-03
2014-10-25 + 2 days = 2014-10-26 (here is the case I need to treat).
This difference appear because of the clock going back 1 hour. Practically 2014-10-27 00:00:00 becomes 2014-10-26 23:00:00.
A simple solution would be to compute this at another hour (example 3 AM). But I want to just display a note when this happens.
For example, if user inputs 2014-10-25, I show a popup saying [something].
Now here is the real problem... I can't seem to find any algorithm that says when clocks goes back in year X.
Example... in 2014 the day is 26 October. In 2016 is 30 October (https://www.gov.uk/when-do-the-clocks-change). Why? This date looks random to be, but I don't think it is. So... when does clock go back/forward?
EDIT: All answers/comments are helpful related to how to fix the problem. But... I already passed that stage. Now I only have an itch about "how on earth are the days when clock is changed computed?".
To find the difference between two dates in whole days, create Date objects, subtract one from the other, then divide by the milliseconds in one day and round. The remainder will only be out by 1 hour for daylight saving so will round to the right value.
You may also need a small function to convert strings to Dates:
// Return Date given ISO date as yyyy-mm-dd
function parseISODate(ds) {
var d = ds.split(/\D/);
return new Date(d[0], --d[1], d[2]);
}
Get the difference in days:
function dateDiff(d0, d1) {
return Math.round((d1 - d0)/8.64e7);
}
// 297
console.log(dateDiff(parseISODate('2014-01-01'), parseISODate('2014-10-25')));
If you want to add days to a date, do something like:
// Add 2 days to 2014-10-25
var d = new Date(2014, 9, 25);
d.setDate(d.getDate() + 2);
console.log(d); // 2014-10-27
The built–in Date object takes account of daylight saving (thought there are bugs in some browsers).
I prefer adding days this way:
var startDate = //someDate;
var endDate = new Date(startDate.getFullYear(),
startDate.getMonth(),
startDate.getDate()+1);
This way you don't have to worry about the days in the calendar.
This code add 1 day, if you want to add more, change the startDate.getDate()+1 for startDate.getDate()+NUMBER_OF_DAYS it works fine even if you are on the last day of month i.e. October 31th.
But maybe you can use #RobG solution which is more elegant than mine
There are dates stored as timestamp in the MySQL database. If I view them with phpMyAdmin the correct time is shown. In a php script I try to output the date with UNIX_TIMESTAMP into a Javascript Date Object (new Date()). When displaying the data in a Google Chart there is a time offset of +2:00 hours (my current timezone). I also looked into the timestamp and a timestamp converter told me that the local time is correct and UTC time is -2:00 hours.
In the php-script I already set the timezone with date_default_timezone_set(). SELECT ##global.time_zone, ##session.time_zone; outputs SYSTEM. But I still get the time offset. Now I use
SELECT UNIX_TIMESTAMP(CONVERT_TZ(Timestamp, "+02:00", ##session.time_zone)) ...
and I get the correct data. Does this mean that the data is stored with a 2 hours offset? Why does phpMyAdmin showing me the correct date and time? Or does the Google chart expects UTC time and the browser automatically adds the difference for the timezone?
What is the real problem here?
Now I wrote a function which converts the timestamp from the database into an UTC date:
function getDateinUTC(timestamp){
var date = new Date(timestamp * 1000);
var year = date.getUTCFullYear();
var month = date.getUTCMonth() + 1; // getMonth() is zero-indexed, so we'll increment to get the correct month number
var day = date.getUTCDate();
var hours = date.getUTCHours();
var minutes = date.getUTCMinutes();
var seconds = date.getUTCSeconds();
return new Date(year, month, day, hours, minutes, seconds);
}
When I create the DataTable I simply call the function as shown here:
rows: [
{c:[{v:getDateinUTC(stamp)}, {v: value}]},
]
You have to replace stamp and value with your php-code which fills the place.
This idea is based on the article Automatic timezone conversion in JavaScript by David Mytton.
So far the times seems to be correct.
I have two text boxes which accept Start Date and End Date respectively, in format YYYY/MM/DD.
I need to alert the user if he selects an end date that exceeds the start date by 50 days.
Here's what I have so far:
var startDate = new Date(document.getElementsByName('MYSTARTDATE').value);
var endDate = new Date(document.getElementsByName('MYENDDATE').value);
if ((endDate - startDate) > 50)
{
alert('End date exceeds specification');
return false;
}
Just as an example, when I select Start Date as 2012/01/22 and End Date as 2012/02/29
startDate = 'Sun Jan 22 00:00:00 UTC +0530 2012'
endDate = 'Wed Feb 29 00:00:00 UTC +0530 2012'
And the result for endDate - startDate is 3283200000, instead of 38.What am I doing wrong?
3283200000 is 38 days in milliseconds.
38 days x 24 hours x 60 minutes x 60 seconds x 1000 milliseconds
Also, there are 38 days between those two dates, not 39.
An easy solution is to have a variable (constant really) defined as the number of milliseconds in a day:
var days = 24*60*60*1000;
And use that variable as a "unit" in your comparison:
if ((endDate - startDate) > 50*days) {
...
}
The solution by Jeff B is incorrect, because of daylight savings time. If the the startDate is, say, on October 31, and the endDate is on December 20, the amount of time that has actually elapsed between those two times is 50 days plus 1 hour, not 50 days. This is especially bad if your program doesn't care about the time of day and sets all times at midnight - in that case, all calculations would be off by one for the entire winter.
Part of the correct way to subtract dates is to instantiate a new Date object for each of the times, and then use an Array with the number of days in each month to compute how many days have actually passed.
But to make things worse, the dates that Europe changes the clocks are different than the dates that the clocks are changed in New York. Therefore, timezone alone is not sufficient to determine how many days have elapsed; location is also necessary.
Daylight savings time adds significant complexity to date handling. In my website, the function needed to accurately compute the number of days passed is nearly a hundred lines. The actual complexity is dependent on whether the calculations are client side or server side or both and who is viewing the data.