Maximum call stack exceeded trying to set date in paper-date-picker - javascript

With https://github.com/bendavis78/paper-date-picker (based on moment.js)
I am trying to set the date (optionally) offset months in the future.
The element:
<paper-date-picker date="{{date}}"></paper-date-picker>
The following property works:
properties: {
date: {
type: Date
}
}
But this floods the console with "Uncaught RangeError: Maximum call stack size exceeded." from polymer:1258 & polymer-mini:964
properties: {
date: {
type: Date,
value: function() {
var myDate = new Date();
var offset = this.attributes.offset ? parseInt(this.attributes.offset.value) : 0;
myDate.setMonth(myDate.getMonth() + offset);
return myDate;
}
}
}
It doesn't seem to matter what the date transform is, if the "value" block is there it fails.
Logging the values in the function shows the above parses date as I'd expect, but I guess my expectations differ from the component?
Can anyone spot where I'm going wrong?

You need to set the date of the calendar object rather than the date-picker object, e.g. this.$.datepicker-id.$.calendar.date = new Date();
That worked in terms of resetting the date for the picker, but I actually encountered a different issue afterwards related to not being able to reselect the same date that I previously selected after closing the dialog. I had to remove the logic in calendar._updateSelection to not set the selected.width to 0px.

I can reproduce the error by plugging in a new Date() (as reported in console):
<paper-date-picker date="Tue Mar 15 2016 17:32:36 GMT+0000 (GMT Standard Time)"></paper-date-picker>
So even though this is a valid datetime, I guess the date picker is not happy about the format of myDate for one reason or another. I think you should try converting that date to a string in the format mm/dd/yyyy. As a quick proof-of-concept, try:
properties: {
date: {
type: Date,
value: function() {
return '03/15/2016';
}
}
}

Related

Date Range is starting with Plus

I have created a small function which give all dates between two dates.
but this is starting from Plus 1 date.
Here's my code (also on Here is jsfiddle):
function DateRangeArr(to, from) {
console.log(to);
console.log(from);
var Dateresult = [];
var end = new Date(from);
var loop = new Date(to);
while (loop <= end) {
Dateresult.push({ 'total': 0, 'log_date': loop });
var newDate = loop.setDate(loop.getUTCDate() + 1);
loop = new Date(newDate);
}
return Dateresult;
}
console.log(DateRangeArr('2020-12-05','2020-12-12'));
It's giving me results starting from 2020-12-06 to 2020-12-13. Also will it gives result depending upon user time zone ?
There are a couple of things going on that could account for the problem.
(This is probably the thing you're seeing) You're changing the state of the Date instance that you added to the array after adding it. That changes the instance that's in the array.
Since "2020-12-05" is a date-only string, it's parsed as UTC in specification-compliant browsers (see the rules at Date.parse), so the Date objects will represent midnight on that date UTC rather than midnight on that date in your local timezone. If you want them to reliably be midnight local time, add T00:00 to the string. If you want them to be parsed reliably as UTC, you should be able to use them as-is, but the spec moved around on this (ES2015 said they should be parsed as local time, not UTC, before being updated by ES2016) so to get UTC reliably, add T00:00Z to it. (My understanding is that the spec allows just adding a Z, but others read the spec differently, and both Safari's JavaScriptCore and Firefox's SpiderMonkey reject new Date("2020-12-05Z"), so add T00:00Z.) Or use new Date(Date.UTC(year, month - 1, day)) instead.
You're mixing up accessors here: loop.setDate(loop.getUTCDate() + 1). That's using the UTC accessor to get the date, but then the local time accessor to set it. You need to be consistent in order to add a day to the date.
You haven't said how you're using the resulting array of Date objects, but just note that the date they show may seem off if (for instance) you parse them as UTC but then display the result in local time or vice-versa, because of the time zone offset.
You have to and from reversed in your code. You're using them consistently, but it's quite hard to read. :-) When building an array in date order, it goes from the earlier date to the later date.
Here's a version updated to work entirely in UTC; the resulting Date objects represent midnight UTC on each of the dates:
function dateRangeArr(from, to) {
console.log(from);
console.log(to);
var dates = [];
var end = new Date(to + "T00:00Z");
var loop = new Date(from + "T00:00Z");
while (loop <= end) {
dates.push({ "total": 0, "log_date": new Date(+loop) });
loop.setUTCDate(loop.getUTCDate() + 1);
}
return dates;
}
console.log(dateRangeArr("2020-12-05","2020-12-12"));
(I've also updated the function and variable names to be more consistent with standard practice in JavaScript, since the function isn't a constructor function.)
Here's a version that works in local time instead:
function dateRangeArr(from, to) {
console.log(from);
console.log(to);
var dates = [];
var end = new Date(to + "T00:00");
var loop = new Date(from + "T00:00");
while (loop <= end) {
dates.push({ "total": 0, "log_date": new Date(+loop) });
loop.setDate(loop.getDate() + 1);
}
return dates;
}
console.log(dateRangeArr("2020-12-05","2020-12-12"));
Which you use depends on whether you want the Date instances to represent midnight UTC (use the UTC version) or midnight local time (use the local time version).

moment-timezone change utc to default timezone

Context:
I need to parse datetimes from UTC into the timezone currently set as default by moment-timezone with moment.tz.setDefault.
Attempt (functional):
const task = {
startDate: '2020-03-24 14:00:00'
};
const startDateMoment = moment.utc(task.startDate).tz(moment().tz());
However, I am creating a new moment object every time I need to set the timezone. Is there a more performant way to converting between utc to the default timezone, or getting the default timezone from moment?
moment.tz.guess() guesses the timezone from the browser, not the one set manually.
console.log(`default timezone: "${moment().tz()}", guessed timezone: "${moment.tz.guess()}"`);
returns
default timezone: "US/Samoa", guessed timezone: "America/Vancouver"
After a bit of digging, I did find the following, undocumented, use-at-your-own-risk, could-disappear-at-any-time property:
moment.defaultZone.name
moment.defaultZone is a Zone Object, of which we really only care about the name property.
Note that it is null if you haven't set a default yet! In the code below, I'm taking advantage of a couple new JavaScript features, optional chaining and the nullish coalescing operator to see if the default zone is set and if not, use the moment.tz.guess() value.
const task = {
startDate: '2020-03-24 14:00:00'
};
console.log('before setting default: ', moment.defaultZone);
moment.tz.setDefault('US/Samoa');
console.log('after setting default: ', moment.defaultZone);
const startDateMoment = moment.utc(task.startDate).tz(moment.defaultZone?.name ?? moment.tz.guess());
console.log(startDateMoment.format());
<script src="https://momentjs.com/downloads/moment.min.js"></script>
<script src="https://momentjs.com/downloads/moment-timezone-with-data.min.js"></script>

Moment js: moment(0) = Wed Dec 31 1969?

I tried to make null date.
so I tried to make them all 0 when I click the clear button.
this.clear = function () {
_this.newQuarters.forEach(function (_value, index) {
_value.startDate = 0;
_value.endDate = 0;
_value.suppressAllocation = false;
_value.quarters.forEach(function (_childValue, index) {
_childValue.startDate = 0;
_childValue.endDate = 0;
_childValue.suppressAllocation = false;
});
});
};
}
After that, I tried to add 0 at moment from other function.
this.newQuarters.forEach(function (_value, index) {
var startDate = moment(_value.startDate);
but, it display startDate = Wed Dec 31 1969.
Please help me to find to make all date are null.
When passing a number to the moment() function, it interpret it as a unix timestamp.
Which is the number of second since EPOCH time, or 01-01-1970.
So passing 0 to that function result in the very first second of jan 1 1970. As Bergi pointed out, you are probably displaying your dates in your local timezone, which could result in a time before 01-01-1970.
If you want to create a null date, you should set your startDate to null and handle it correctly ( with an if statement).
You could also set the date back to the current time by passing no argument to the moment() function.
Dates can be tricky to work with in an application. There is no such thing as time that is not time. At least not in the world of programming. For this reason we have to create our own understanding of what a lack of time will be.
There is no time without time but there is a lack of value.
You obviously understand this, you had an approach, in your case, you seem to be fine with simply having time be zero, it just broke when working with moment as moment is using EPOCH time. Thus, zero is time.
You are going to have to test like the rest of us.
this.newQuarters.forEach(function (_value, index) {
var startDate = _value.startDate ? moment(_value.startDate) : null;
Lack of time could be whatever you want, undefine, null, a beginning date
Be consistent: Database vendors and languages handle things differently, front end is not always the same time zone, etc.
If you are dealing with momentjs library, there is a function: invalid()
You can easily make your variables invalid moment object and control their validity.
let currentDate = moment(); // Valid moment object
console.log(currentDate.format());
// make the moment object invalid
currentDate = moment.invalid();
console.log(currentDate.isValid()); // Check validity
console.log(currentDate.format()); // Invalid date
// make the moment object valid again
currentDate = moment();
console.log(currentDate.isValid()); // Check validity
console.log(currentDate.format()); // A valid date
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

How to fix opening time minutes for whole week using DateTime Picker?

Using DateTimepicker I want to set store opening time as 10:30 AM (for example) for the whole week. Using this piece of code I could able to restrict hours.
var curentDate = new Date();
var lastDate = new Date();
lastDate.setDate(curentDate.getDate() + 6);
$('#txtdate').datetimepicker({
inline: true,
sideBySide: true,
maxDate: lastDate,
minDate: curentDate,
enabledHours: HoursArray()
});
I set this to 15min increment but I'm not sure how to set minutes for all the days in a week. Also I want to disable minutes before 10:30 AM each day.
Can some one guide me on this?
I don't see the library exposing any ways to set the default time for each day, but you can take control into your own hands by using their events API and date() method. You could listen for change event Like this:
$(document).on('dp.change', manipulateTime);
The event shows the new date and oldate of the calendar. If the dates are different then you can change the time for new date using the date() method.
function manipulateTime(e){
if(!e.date.isSame(e.oldDate, "day")){
$(e.target).data("DateTimePicker").date(e.date.set({
'hour' : 10,
'minute' : 30
}));
}
}
Further Explanation
The when the event fires it returns three necessary references, date,olddate,target.
Calling DateTimePicker Functions
Note according to their documentation you can use their methods like this: All functions are accessed via the data attribute e.g.
$('#datetimepicker').data("DateTimePicker").FUNCTION()
Using Events
When you call the dp.change event. The call back function will return an object e that has the following accessible properties:
The e property
e = {
date, //date the picker changed to. Type: moment object (clone)
oldDate //previous date. Type: moment object (clone) or false in the event of a null,
target // targeted date picker,
and more...
}
This is the final thing I did to fix my both issues
var futureHour = (new Date(td.date)).getHours();
var futureMin = (new Date(td.date)).getMinutes();
//This is to re-loop time when user tries to select time below 1st pickup time
if(futureHour <= storeOpenHour && futureMin < storeOpenMinutes){
$(td.target).data("DateTimePicker").date(td.date.set({
'hour' : storeOpenHour,
'minute' : storeOpenMinutes
}));
}
//This is to select 1st pickup time on day change
if(!td.date.isSame(td.oldDate, "day")){
$(td.target).data("DateTimePicker").date(td.date.set({
'hour' : storeOpenHour,
'minute' : storeOpenMinutes
}));
}

HTML passing parameters to javascript function that then does a date compare and then javascript returning a result to be displayed in html

I am having problems figuring out how to do a date compare in Javascript, and how to pass and receive varialbes to and from Javascript Function and Html.
I have 4 term dates (workshop start and end dates for each term). I will send one set of dates at a time to the javascript function, and then I want the Javascript to check if today's date falls within the range of that workshop. Then the javascript should return a value like "workshop finished", "workshop in progress", "workshop to come" (depending on wheiter todays date is before, during, or after that specific date range). I'll call the function 4 different times - each with a different range of dates.
So for example, If the first set of dates are: 6th February till 13th March 2014, then how would I call the javascript function? This is what I have so far:
In the html - at the point where I want the status to be displayed, I tried this:
<script language="JavaScript" type="text/javascript">
<!--//
document.write(displayStatus(02062014, 03132014));
//-->
</script>
<noscript></noscript>
I know that the above date formating is probably wrong that I am trying to send to the function, but I am not sure what format is needed to do a date compare. (Note: the empty noscript tags are because if scripting is turned off, I don't want anything displayed.)
I've started the function like this (found inside status-date.js file):
function displayStatus(fromDate,toDate) {
todayDate = new Date();
// this is a comment for code that needs to be written:
//
// magic happens here that compares today's date to the fromDate and toDate
// and returns th appropriate status line
//
// the rest below is how I think the status is returned to the html
// (I'm using 'in progress' as a test example)
var dateStatus = "in progress"
return dateStatus;
}
Note: the function is loaded in from the head section as follows:
<script src="assets/js/status-date.js" language="javascript" type="text/javascript"></script>
Even with this simple function.. that basically gives me the status without any calculations, just so I can test the comunication between HTML and function.. it doesn't display anything. So I can't really move forward until I figure out this basic step first.
So, could some kind sole help me figure this out.
How to properly send formated date parameters to the javascript function.
How to display the status results that need to be returned to the html
How do you (inside the function) check if todays date falls within a range of provided dates.
Thanks for any help provided.
SunnyOz
I believe that you are looking for something like this...
function displayStatus(fromDate,toDate) {
var status;
var today = new Date();
today = Date.parse(today);
if(today >= fromDate && today <= toDate) {
status = 'In Progress';
} else if(today > toDate) {
status = 'Workshop Finished';
} else {
status = 'Workshop To Come';
}
return status;
}
<script>
window.onload = function(){
var startDate = new Date(2014,1,6); //6th February
var endDate = new Date(2014,2,13); //13th March 2014
document.write(displayStatus(Date.parse(startDate), Date.parse(endDate)));
};
</script>
Here are some other helpful resources:
Compare two dates with JavaScript
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

Categories

Resources