Saving moments to use as events in React-Big-Calendar - javascript

I'm having trouble generating events for react big calendar. When making a new event object (in another component), I set the id, event name, just fine, and then I wonder if I'm setting start and end correctly. I'll have a moment like this (created with moment.js) date = 05/15/2018 11:00 AM, and when setting the start/end fields of an event I will set them as new Date(date). For now I am saving this value in local storage, but it eventually will go to a database. I checked, and when I create a constant at the top of my component with my moments, and the new Date() syntax explicitly in the code it works fine, but my pre-made saved dates are not working. I am getting the following error.
index.js:209 Uncaught TypeError: date[("get" + method)] is not a function
at Object.hours (index.js:209)
at Object.isJustDate (dates.js:91)
at TimeGrid.js:237
My question is how should I go about saving my moment so that it can be correctly interpreted by react big calendar?

I answered my own question, Store `new Date ()` in JSON object
You can't store a Date as a Date in JSON, you have to convert it, so I will do so.

Related

Get JavaScript local date from Moment JS

Consider the code :
let now = moment();
console.log(now.format()); // 2019-11-25T20:23:50+02:00
console.log(now.toDate()); // 2019-11-25T18:23:50.916Z
This is the output on my local machine , and when I check the app on Heroku
it gives the same values , even though I changed the TZ like this :
heroku config:add TZ="Asia/Jerusalem"
How can I get a JavaScript Date (Not a String !) object of my localtime , meaning 2019-11-25T20:23:50 ?
Let's walk through your code example:
let now = moment();
You create a Moment object. You don't pass any parameters, so it is initialized using the current timestamp (as if you called Date.now()) and set to "local mode".
console.log(now.format()); // 2019-11-25T20:23:50+02:00
By calling format, you ask the Moment object to produce a String. Since it's in local mode, the offset that applies to that moment in time for the local time zone is emitted in the result, and the wall time shown in the result is adjusted for that offset. In this case, the local time is two hours ahead of UTC. You then pass that string to console.log, which emits it to the console.
console.log(now.toDate()); // 2019-11-25T18:23:50.916Z
By calling toDate, you ask the Moment object to create a Date object. The "mode" of the moment object is no longer relevant because Date objects don't track anything other than a timestamp. Thus, the timestamp within the Moment object becomes the timestamp for the resulting Date object. Since you derived the Moment object from the current time, the result is the same as if you just called new Date() to begin with.
You then pass the string to console.log - except one can't just log an object, so it first has to convert it to something so you can see it. Here's the interesting part: There is no spec for this behavior. Implementations of ECMAScript can do whatever they like in this regard. Some implementations, like in your example, will call .toISOString() and log the result. Since .toISOString() displays the result in UTC, the result of logging a Date object is also shown in UTC. But other implementations will call .toString() on the Date object and log that, the result being in local time. It's entirely possible some future implementation could show the result in some graphical or interactive output. The point being, you can't rely on the behavior of console.log(Date) to be consistent.
No amount of changing your time zone settings will change this result. The Date object is inherently UTC-based, your output is also UTC-based, and UTC is the same over the whole planet (by design).
If you want the time zone reflected in the string output, you must use a function that produces a string with respect to local time. As you showed, you'll get that with .format() on a Moment object in local mode. You can also get one from calling .toString() on a Date object (but the resulting string is not in the same ISO 8601 format).
i would try,
moment().local().toDate()
but if you are planning to save date into db it's good practice to save time in UTC format for easier global conversion.
If you want to work timezones you may require also moment timezone package - https://momentjs.com/timezone/docs/
npm install moment-timezone
Hope this helps :)

How can I insert or update a js-timestamp component after the page has loaded?

Background: I'm using the SailsJS framework to display the timestamp of when a data model was updated. The framework comes from something they call 'parasails', which uses Vue.js. It provides the <js-timestamp :at="1573487792252"> component to display a message like "a few seconds ago" which automatically updates as time passes. As time passes by, the "time since" message will dynamically update so it might say something like "5 minutes ago." Simultaneous to this, the underlying model in my project can be updated and that update gets passed to the browser with a WebSocket. When that happens, I want to update the <js-timestamp> to reflect the new reference timestamp.
Problem: When the HTML first loads, parasails replaces the <js-timestamp> element with a <span parasails-component="js-timestamp"> which contains the literal "time since" message and not the integer timestamp. Presumably, parasails stores that integer in a JavaScript variable. I have tried using JQuery to insert a new <js-timestamp> but parasails does not catch on. The tag remains in the DOM, but it doesn't get updated with a "time since" message. I can see from the source code of the js-timestamp component that it uses the moment(this.at).fromNow() to get the "time since" message when the timestamp is less than 24 hours old, but if I use that and replace the text manually, it no longer updates on its own as time passes.
Question: What is the proper way to update the timestamp so that parasails (or Vue.js or whatever) continues to update the message as time passes?
As it turns out, I can just define a variable in the JavaScript associated with the page and set the js-timestamp :at attribute to the variable name instead of an integer literal. Then when the variable updates, so does the page.
Instead of this:
<js-timestamp :at="1573487792252">
I now use this:
<js-timestamp :at="model.updatedAt">

Ember.js - ember-pikaday not allowing preset date

I am trying to create a datepicker in ember.js using the ember-pikaday addon. The datepicker should have a date in it when it is displayed. So, I added the following code to my template:
{{pikaday-input value=rental.date format="MMMM Do YYYY" yearRange="2016" useUtc=true}}
However, even though I specify the value as rental.date, the input is blank. I know that the value of rental.date is not null because when I set the placeholder to rental.date, the placeholder's date is correct.
The problem with your case is due to the fact that you are passing a momentjs object to ember-pikaday directly. Instead of passing the momentjs object directly just create a computed property called as follows on your owner component:
rentalDate:Ember.computed('rental.date', function() {
return this.get('rental.date').toDate();
}),
and perform binding to rentalDate. ember-pikaday does not handle momentjs object passed in by itself, just extract the actual javascript date object via toDate() as shown in code snippet above. Just for clarification you can also pass formatted string to ember-pikaday such as "25/05/2016", "2016.05.25", etc. It will also handle such string values properly.

new Date(epoch) returning invalid date inside Ember component

I have a date-filter component that I am using in my Ember application that only works on initial render, not on a page reload, or even if I save a file (which triggers the application to live update).
In the main template of my application, I render the date-filter like this passing it a unix timestamp
{{date-filter unixepoch=item.date}}
Then, in components/date-filter.js, I use a computed property called timeConverter to change the unix epoch into a time string formatted according to user's language of choice, and then in my templates/components/date-filter.hbs file I do {{timeConverter}} to display the results
timeConverter: function(){
//step 1: get the epoch I passed in to the component
var epoch = this.get('unixepoch');
//step 2: create a human readable date string such as `Jun 29, 2015, 12:36PM`
var datestring = new Date(epoch)
//do language formatting --code omitted as the problem is with step2
}
It is step 2 that fails (returning invalid date) if I refresh the page or even save the file. It always returns the proper date string the first time this component is called. Even if I do new Date(epoch) in the parent component, and try to pass the result in to this component (to do foreign language formatting), I'm having the same problem.
Question: how can I figure out what's happening inside new Date(epoch), or whether it's an issue related to the component?
I suspect your epoch value is a string (of all digits). If so, then
var datestring = new Date(+epoch);
// Note ------------------^
...will fix it by converting it to a number (+ is just one way to do it, this answer lists your options and their pros/cons). Note that JavaScript uses the newer "milliseconds since The Epoch" rather than the older (original) "seconds since The Epoch." So if doing this starts giving you dates, but they're much further back in time than you were expecting, you might want epoch * 1000 to convert seconds to milliseconds.
If it's a string that isn't all digits, it's not an epoch value at all. The only string value that the specification requires new Date to understand is the one described in the spec here (although all major JavaScript engines also understand the undocumented format using / [not -] in U.S. date order [regardless of locale]: mm/dd/yyyy — don't use it, use the standard one).

OData Date Filtering from JS

I am using the DXTREME framework from Devexpress to connect a HTML mobile app to an OData source.
One of my tables in SQL Server, exposed through the OData service is a table with a date (not datetime) field in it. It is exposed through OData like this:
<d:TaskDate m:type="Edm.DateTime">2010-04-01T00:00:00</d:TaskDate>
I am trying to filter the data on this field through a calendar control, but when I try to filter the datasource on the JS side, I get no matches. This is because the date is passed to the OData service, I believe, in UTC format, so if I query for TaskDate = '10/JUL/2013', I believe the date is passed as "09/JUL/2013 14:00". If I filter on TaskDate > '10/JUL/2013' I get results back from after "09/JUL/2013 14:00" at any rate.
I have tried declaring a new date with no time part:
filterDate = new Date(2013, 6, 10)
but is still doesn't work, it still subtracts 10 formy time zone on the JS side.
What I want to do is to return a lists of Tasks valid on that particular date. How can I achieve this?
I think my problem was the confusion around the dxDateBox control returning just a date, and that date being changed when passed to my odata service.
I solved the issue by converting the date to UTC myself, but just using the Date parts from the control, (where filterDate came from the control):
var paramDate = new Date(Date.UTC(this.filterDate().getFullYear(), this.filterDate().getMonth(), this.filterDate().getDate()));
this.dataSource.filter(["TaskDate", "=", paramDate]);
This works nicely, but seems rather verbose.

Categories

Resources