chart.js - display control timescale time zone - timezone

I want to configure one chart to have a different timezone (for example I'm in utc+00 and want to display data in utc+01)
Is there a way? according to docs I have to return a moment object, and then date displays according to moment global locale.

In the time configuration options specify parser as a function:
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'hour',
min: minDate,
max: maxDate,
displayFormats: {
hour: 'HH'
},
parser: function (utcMoment) {
return utcMoment.utcOffset('+0100');
}
}
}]
As well as converting the chart values this will also apply to the min/max values of the x axis.
This assumes your min/max values and label array is populated with moment objects. If dealing with date objects then the function needs to convert the date to a moment first.
parser: function(date) {
return moment(date).utcOffset('+0100');
}

I use a callback on the ticks function. That way you only change the label.
import Moment from 'moment';
//...
const options = {
scales: {
xAxes: [{
type: 'time',
ticks: {
callback: (label, index, ticks) => {
const format = 'DD HH'; // Change how you please
return new Moment(ticks[index].value)
.utcOffset(this.timeZoneOffsetSeconds / 60)
.format(format);
}
}
}]
},
// other options removed for clarity
};
this.chart = new Chart(chartElem, {
options: options,
// other parameters removed for clarity
});
Note on the example: Moment is deprecated, apparently there are better libraries out there but that's what I have in my codebase so...

Related

Get Rid of Saved Duplicates from Web Scraped Data On Google Sheets

The code that was given to me works by saving web scraped data in google sheets, however, when it saves data it creates duplicates of the same data entry from previously scheduled web scrapes. Is there a way we can create a code where it only saves unique rows and adds in edited/ updated info? I have added the code below:
function myFunction() {
SpreadsheetApp.getActiveSheet().getRange('A1').setValue('=importdata("https://www.parsehub.com/api/v2/projects/tZOywrNXQ3Q4/last_ready_run/data?api_key=tn6CGEyTTVxE&format=csv")')
}
// custom menu function
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Custom Menu').addItem('Save Data','saveData').addToUi().
}
// function to save data
function saveData() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sh4=ss.getSheetByName('Zapier Tax Leads');
var sh3=ss.getSheetByName('Current Tax Leads')
var data=sh3.getRange(1,1,sh3.getLastRow(),33).getValues();
sh4.getRange(sh4.getLastRow()+1,1,data.length,data[0].length).setValues(data);
}
function removeDuplicates() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Zapier Tax Leads')
var data = sheet.getDataRange().getValues();
var newData = new Array();
for(i in data){
var row = data[i];
var duplicate = false;
for(j in newData){
if(row.join() == newData[j].join()){
duplicate = true;
}
}
if(!duplicate){
newData.push(row);
}
}
sheet.clearContents();
sheet.getRange(1, 1, newData.length,
newData[0].length).setValues(newData);
}
Edit:
The tab labeled "Zapier Tax Leads" is where the code copies over the duplicate data.
In tab "Current Tax Leads" the columns that we will be updating are only column H through O.
Spreadsheet link: https://docs.google.com/spreadsheets/d/1G1PLs46cnQ-CyJWBI0ibKNmYosSEQRcrAGE8Qx2MArU/edit?usp=sharing
Not the exact solution but the sheet-api's DeleteDuplicatesRequest should work.
I have not tested it, but this should work. (I presume you use the drive package for nodejs?)
var requests = {
"requests": [{
"deleteDuplicates": {
//rows to operate on
//first value is kept if there are duplicates
"range": {
"sheetId": integer,
"startRowIndex": integer,
"endRowIndex": integer,
"startColumnIndex": integer,
"endColumnIndex": integer
}
,
// The columns in the range to analyze for duplicate values.
// If no columns are selected then all columns are
// analyzed for duplicates.
"comparisonColumns": [{
"sheetId": integer,
"dimension": "COLUMNS",
"startIndex": integer,
"endIndex": integer
}]
}
}]
}
sheets.spreadsheets.values.batchUpdate(spreadsheetId=spreadsheet_id,body=requests)

How to disable the past dates in the Kendo date picker?

How to disable the past dates in the Kendo date picker ? ( Date Picker validation)
That will allow the user to select only the current date and future date.
In the HTML :
#Html.EditorFor(Model => Model.AppointmentDate)
In the JQuery :
$('#AppointmentDatee').data('kendoDatePicker')
The shortest way to disable past dates is using min parameter with current date value:
var presentDate = new Date();
$(function () {
var datepicker = $('#AppointmentDate').kendoDatePicker({
value: presentDate,
min: presentDate,
}).data('kendoDatePicker');
});
If you're using Razor with #Html.Kendo() helper, use DatePickerBuilderBase.Min() method:
#(Html.Kendo().DatePicker().Name("AppointmentDate").Min(DateTime.Today))
However, the min parameter will remove all disabled past dates (i.e. they're not shown in calendar view). If you want to show disabled dates but the user cannot interact with them (by clicking the date), use k-state-disabled CSS class in empty option inside month parameter:
var datepicker = $('#AppointmentDate2').kendoDatePicker({
value: presentDate,
min: presentDate,
month: {
empty: '<div class="k-state-disabled">#= data.value #</div>'
}
}).data('kendoDatePicker');
If #(Html.Kendo()) helper is used, use DisabledDates to call a function which disables past dates like example below:
<script>
var getPastDates = function(begin, end) {
for (var dtarr = [], date = start; date < end; date.setDate(date.getDate() + 1)) {
dtarr.push(new Date(dt));
}
return dtarr;
}
function disablePastDates(date) {
var pastDate = getPastDates(new Date('0001-01-01T00:00:00Z'), new Date());
if (date && compareDates(date, dates)) {
return true;
}
else {
return false;
}
}
function compareDates(date, dates) {
for (var i = 0; i < dates.length; i++) {
if (dates[i].getDate() == date.getDate() &&
dates[i].getMonth() == date.getMonth() &&
dates[i].getYear() == date.getYear()) {
return true;
}
}
}
</script>
Helper usage:
#(Html.Kendo().DatePicker().Name("AppointmentDate").DisableDates("disablePastDates"))
Working examples:
JSFiddle demo 1 (hidden past dates)
JSFiddle demo 2 (grayed-out past dates)
References:
Kendo.Mvc.UI.Fluent.DatePickerBuilderBase.Min(DateTime)
Show Out-of-Range Dates as Disabled
Kendo MVC DatePicker - Disable dates
Similar issue (with different approach):
How to disable past dates without hiding them in Kendo date picker?
if you use jquery for your kendoDatePicker , this code may help you!
$("#MyDatapickerElement").kendoDatePicker({
value: new Date(),
disableDates: function (date) {
if (date <= new Date()) {
return true;
} else {
return false;
}
}
});
If using Html.Kendo().DatePicker() you can show the disabled dates using the MonthTemplate. Example below shows the Minimum Date set to DateTime.Today and sets the MonthTemplate to show past dates as disabled.
Html.Kendo().DatePicker()
.Name("MyDate")
.Min(DateTime.Today)
.MonthTemplate(m=>m
.Empty("<div class=\"k-state-disabled\">#= data.value #</div>")
)

Date timezone is lost between my AngularJS controller and Backend entity framework

I'm facing an issue with date timezoning missed between AngularJS and Entity Framework.
This is a sample of my angular code: PLNKR
I get date from server side (ASP.NET MVC5) as string like this: "2015-02-17T00:00:00" without any info about timezone.
To parse this string as date and bind it to input[date], I'm using angularjs directive for this.
My problem is: my local timezone is +4, after changing the value and pushing it back to the ngModel, it is converted to UTC time, so date part will be -1 day back. In other words, if I select Feb 18, 2015 in the date input, the ngModel value will be: 2015-02-17T20:00:00.000Z. So, when passed back to the server, I receive it in the controller like this:
{5/17/1988 8:00:00 PM}
Date: {5/17/1988 12:00:00 AM}
dateData: 5238841010427387904
Day: 17
DayOfWeek: Tuesday
DayOfYear: 138
Hour: 20
InternalKind: 4611686018427387904
InternalTicks: 627154992000000000
Kind: Utc
Millisecond: 0
Minute: 0
Month: 5
Second: 0
Ticks: 627154992000000000
TimeOfDay: {20:00:00}
Year: 1988
The kind of this date is Utc. But when I pass it to the DB throught Entity framework (v6) it is saved without any timezoning. So, next time I'm loading it, it will be in local timezone, so with -4 hours from the original value, which is wrong.
This date attribute in entity framework model is simple, just like this public DateTime BirthDate { get; set; } and in DB (MSSQL) it is of type DateTime like this: [BirthDate] DATETIME NOT NULL
I think the solution should be: either to force Angular to use only local timezone, while my application will run only locally, or to force entity framework to save timezone info.
I prefer to go with first option, but how?
I solved this issue by changing the return type of angularJS directive from Date object to string with yyyy-mm-dd format.
Before:
(function() {
function parseDateString(dateString) {
if ('undefined' === typeof dateString || '' === dateString) {
return null;
}
var parts = dateString.split('-');
var year = parseInt(parts[0], 10);
var month = parseInt(parts[1], 10);
var day = parseInt(parts[2], 10);
return new Date(year, (month - 1), day);
}
var mainApp = angular.module('mainApp', [])
.directive('input', ['dateFilter',
function(dateFilter) {
return {
restrict: 'E',
require: '?ngModel',
link: function(scope, element, attrs, ngModel) {
if ('undefined' !== typeof attrs.type && 'date' === attrs.type && ngModel) {
ngModel.$formatters = [ function(modelValue) { return dateFilter(modelValue, 'yyyy-MM-dd'); } ];
ngModel.$parsers = [ function(viewValue) { return parseDateString(viewValue); } ];
}
}
}
}
]).controller("myController", function($scope) {
$scope.testDate = "2015-02-17T00:00:00";
});
}());
After:
(function() {
var mainApp = angular.module('mainApp', [])
.directive('input', ['dateFilter',
function(dateFilter) {
return {
restrict: 'E',
require: '?ngModel',
link: function(scope, element, attrs, ngModel) {
if ('undefined' !== typeof attrs.type && 'date' === attrs.type && ngModel) {
ngModel.$formatters = [
function(modelValue) {
return dateFilter(modelValue, 'yyyy-MM-dd');
}
];
ngModel.$parsers = [
function(viewValue) {
return dateFilter(modelValue, 'yyyy-MM-dd');
}
];
}
}
}
}
]).controller("myController", function($scope) {
$scope.testDate = "2015-02-17T00:00:00";
});
}());

Highchart xAxis labels formatter not displaying returned value

I've been fighting this problem for most of the day now, so I figure I'd ask here...
I'm creating a plot using highcharts, and I want to use a datetime xAxis. The label I wish to show on this axis is a calculated value, relative to a set of specific dates. So I use a labels.formatter function which have access to the previous and the last dates, and relative to these dates I do some logics.
The logic is that if this.value (from within the formatter) is before the last one, the axis should show months since previous ones, if this.value == last it should show 0 and if this.value > last it should show months since last.
I have some helper functions that are called in my code, they have been used in many occasions and work as they should.
Below is the implementation of my label formatter for the xAxis.
gVars.reportAddedResistance.MonthSinceUsed = new Array();
this.highchart.options.xAxis.labels.formatter = function() {
var mbDec;
var mod;
var result;
var returnValue = null;
var isSet;
var previous = new Date(self.data.plotConf.previousDrydockDate);
var last = new Date(self.data.plotConf.lastDrydockDate);
var val = new Date(this.value);
if(val.getTime() < last.getTime()) {
// BEFORE LAST DRYDOCK
mbDec = Utils.monthsBetweenDecimal(previous, val);
mod = mbDec % 1;
if(mod <= (1 / 30.4375)) {
result = Math.round(mbDec);
isSet = gVars.reportAddedResistance.MonthSinceUsed.indexOf(result);
if(isSet == -1) {
gVars.reportAddedResistance.MonthSinceUsed.push(result);
//console.log('',"LESS Returning "+result+" Used: "+gVars.reportAddedResistance.MonthSinceUsed);
returnValue = result;
}
}
}
else if(val.getTime() == last.getTime()){
// AT LAST DRYDOCK
var result = 0;
isSet = gVars.reportAddedResistance.MonthSinceUsed.indexOf(result);
if(isSet == -1) {
gVars.reportAddedResistance.MonthSinceUsed.push(result);
//console.log('',"EVEN Returning "+result+" Used: "+gVars.reportAddedResistance.MonthSinceUsed);
returnValue = result;
}
}
else if(val.getTime() > last.getTime()){
// AFTER LAST DRYDOCK
mbDec = Utils.monthsBetweenDecimal(last, val);
mod = mbDec % 1;
if(mod <= (1 / 30.4375)) {
result = Math.round(mbDec);
isSet = gVars.reportAddedResistance.MonthSinceUsed.indexOf(result);
if(isSet == -1) {
gVars.reportAddedResistance.MonthSinceUsed.push(result);
//console.log('',"MORE Returning "+result+" Used: "+gVars.reportAddedResistance.MonthSinceUsed);
returnValue = result;
}
}
}
return returnValue;
};
The value of previous is (from console.log):
Date {Tue Jun 15 2010 02:00:00 GMT+0200 (Romance Daylight Time)}
The value of last is (from console.log):
Date {Sat Jun 15 2013 02:00:00 GMT+0200 (Romance Daylight Time)}
If I enable the console.log output I get this output, which to me indicates that the logics and date comparisons is working as expected:
LESS Returning 31 Used: 31
LESS Returning 32 Used: 31,32
LESS Returning 33 Used: 31,32,33
LESS Returning 34 Used: 31,32,33,34
LESS Returning 35 Used: 31,32,33,34,35
EVEN Returning 0 Used: 31,32,33,34,35,0
MORE Returning 1 Used: 31,32,33,34,35,0,1
MORE Returning 2 Used: 31,32,33,34,35,0,1,2
MORE Returning 3 Used: 31,32,33,34,35,0,1,2,3
MORE Returning 4 Used: 31,32,33,34,35,0,1,2,3,4
MORE Returning 5 Used: 31,32,33,34,35,0,1,2,3,4,5
MORE Returning 6 Used: 31,32,33,34,35,0,1,2,3,4,5,6
MORE Returning 7 Used: 31,32,33,34,35,0,1,2,3,4,5,6,7
MORE Returning 8 Used: 31,32,33,34,35,0,1,2,3,4,5,6,7,8
My problem is, that the returned values are not displayed on my plot. If I change the formatter function to just return this.value it displays them all, without any problems, but for some reason I cannot identify the return values (as seen in the above console.log output) is not shown.
My xAxis is configured like this:
xAxis: {
type : 'datetime',
dateTimeLabelFormats: {
day: '%Y-%m-%d',
week: '%Y-%m-%d',
month: '%Y-%m-%d',
year: '%Y-%m'
},
startOnTick : false,
tickInterval : 24 * 3600 * 1000 * 1, // 1 day
title : {
text : 'Months relative to drydockings',
style : {
fontSize : '9pt',
fontFamily : 'Arial'
}
},
labels : {
maxStaggerLines : 1,
style : {
fontSize : '7pt',
fontFamily : 'Arial'
}
}
},
I'm stuck - PLEASE HELP!!! :-)
EDIT: I'm using Highcharts JS v3.0.7 (2013-10-24)
The solution to my problem was to add this to the formatter:
if(this.isFirst) {
gVars.noOfSeriesCalled++;
}
if(gVars.noOfSeriesCalled == this.axis.series.length) {
// The stuff thats posted above
}
else {
return null;
}
I think its an error in the library that I have to use a global variable to keep track of how many iterations I've been through.
The correct implementation, as seen from my perspective, would be that the formatting function were called once for each tick in the xAxis, regardless of how many series are added to the plot.

jquery date picker

just wondering is there a way to disable all the weekends in the jquery date picker?
Just having a quick look at the documentation, best guess would be to use the beforeShowDay event to disable the days you don't want to be selectable.
use "$("#datepicker").datepicker({ beforeShowDay: $.datepicker.noWeekends });" (change the id selector to match your field).
Do you not want them to be clickable or do you just want to not display them?
The following will hide them:
$("#yourDatePicker").datepicker({ beforeShowDay: $.datepicker.noWeekends });
If you still want to display the weekends, just not let them be selectable, you can use the beforeShowDay. This will check each day to see if it is a Sunday or Saturday, and if it is, returns false so that it will be disabled.
$(document).ready(function () {
$('#myDatePicker').datepicker({
beforeShowDay: disableWeekends
});
function disableWeekends(date) {
var daysToDisable = [0, 6];
var day = date.getDay();
for (i = 0; i < daysToDisable.length; i++) {
if ($.inArray(day, daysToDisable) != -1) {
return [false];
}
}
return [true];
}
});

Resources