I have a simple form which when submitted enters data into a meteor mongo collection. I then output the data just submitted into another div, kind of like tweets being submitted and shown in a timeline.
I'd like to store the timestamp of when the user submitted the form into the collection and then display the 'feed' ordered by the timestamp descending, so newest first. I'm currently using moment.js to record the timestamp in the collection and then simply use that timestamp on the output, but it doesnt seem the most efficient way to do this.
I intend to have users in different time zones submitting the form and therefore would like to be able to display the timestamps submitted in UTC ordered by most recent.
Currently I have...
Template.form.events({
'submit form': function(e) {
e.preventDefault();
var insertPost = {
timestamp: moment().format('DD-MM-YY HH:mm:ss ZZ')
// some other stuff as well
};
form._id = Posts.insert(insertPost);
)};
Then this is being displayed in my post_item.html :
<template name="post-item">
<div>
<ul class="list-inline">
<li><small>{{timestamp}}</small></li>
// some other stuff too
</ul>
</div>
</template>
Is this way of storing the timestamp ok? I feel storing it in milliseconds is probably better and then formatting that on the output.
So I can change my form.events code to store
timestamp: moment.utc().valueOf(),
and this stores in milliseconds since the epoch, but how do I then convert that within the html template to display the timestamp nicely formatted?
Use moment js to display dates and times in various formats and the atmosphere package has plenty of installs.
http://momentjs.com
https://atmospherejs.com/momentjs/moment
Related
I have initialized a real time database using firebase, I am detecting live changes to the databse using
const ref = firebase.database().ref("test");
ref.on('value', function(dataSnapshot){
console.log(dataSnapshot.val())
});
But this returns me value in ascending order. Whereas I want it to return based on time. I tried using time in: 00:00 (IST) format but if a data is marked 11:59 (am) and another 01:02 (pm) this will return me the second message first.
What will be the best way to fix this?
example data is =>
in my databse =>
It is not clear what you mean by time in ascending order
None of your example data mention time. They are just usernames and text.
If you want to order times correctly, best to use ISO date format
This stores 1:02 pm as 13:02, which will sort after 11:59. Its sorting characteristics are ideal.
Use an international time standard to store your times
An international time standard, UTC, has great advantages over national times. It is not subject to change with location, political decisions, or season. You can always interconvert with the user's local time, at the time of entry or display.
Example
const dateString = (new Date()).toISOString();
console.log(dateString)
// Result:
// 2021-06-22T14:40:37.985Z
// If you want to use them as Firebase keys, they must not contain a ".", so you might clean it up like this:
const cleanDateString = (new Date()).toISOString().replace(".","-")
console.log(cleanDateString)
// Result:
// 2021-06-22T14:47:44-445Z
Even better, use a Firebase PushID
The above date-and-time system will work if you are using it to sort the remarks made by a single person, but will not be good as a message identifier if a single space is shared by all people, since 2 people will eventually make a message at the same millisecond, and will get the same message ID.
To deal with that it is better practice to use a Firebase Push ID.
An explanation is given here: In Firebase when using push() How do I get the unique ID and store in my database
Or from Firebase itself, here:
https://firebase.google.com/docs/database/admin/save-data
I've uncovered an odd bug with Google Apps Script's web interface that it can't seem to transport datetime values from the server side to the client.
// Code.gs
function fetchData(){
var spreadsheet = SpreadsheetApp.openByUrl(SHEET_URL)
var sheet = spreadsheet.getSheetByName("My sheet")
var values = sheet.getDataRange().getValues()
Logger.log(values)
return values
}
// javascript.html
<script>
$(function() {
google.script.run.withSuccessHandler(console.log).fetchData()
})
</script>
If I run the above without any dates in the "My sheet" spreadsheet, it works as expected, with the server side Logger.log and the client side console.log showing the same data. But if I input a date type value into the spreadsheet, the Logger.log will still show everything as expected, but the console.log will simply log null.
I checked the XHR and it appears that the data is in fact making it to the browser, but it looks like something about the de-serialization is breaking. If the date is listed as 7/7/21 in the spreadsheet, it is coming across as Wed Jul 07 00:00:00 PDT 2021 in the XHR.
Any ideas about how to fix are much appreciated! Thank you!
You are describing the documented behavior of google.script.run:
Requests fail if you attempt to pass a Date, Function, DOM element besides a form, or other prohibited type, including prohibited types inside objects or arrays. Objects that create circular references will also fail, and undefined fields within arrays become null.
See the reference given by #Cooper.
To pass datetime values between the client and the server, serialize before sending them across. The easiest way is usually to use date.getTime() and pass as integer. Try this:
const values = sheet.getDataRange().getValues().map(value => {
(Object.prototype.toString.call(value) === '[object Date]')
? value.getTime()
: value
});
On the receiving side, use const date = new Date().setTime(value) to convert the integer back to a Date object.
If you do not know the locations of dates in the spreadsheet, but need to detect them in data, you may want to use a magic prefix like 'date:' + value.getTime().
The database and node are set as -02:00 timezone.
When I save a register, using sequelize, it saves the register with the right date and time in its date fields. For example, if I save a register with the field moment set as '2017-01-15T23:59:59-0200' and look in the database via MySQL Workbench I will see 2017-01-16 00:00:00 in the respective column.
I can even correctly find registers and filter by date and time.
But the value returned by a find operation in the field is '2017-01-16T01:59:59.000Z', meaning it was added two hours to the answer.
How could I retrive the correct date and time from MySQL using Sequelize?
Solved by overhiding String.toJSON:
Date.prototype.toJSON = function(){ return this.toLocaleString(); }
I am working on my first project using Meteor, and am having some difficulty with sorting.
I have a form where users enter aphorisms that are then displayed in a list. Currently the most recent aphorisms automatically display at the bottom of the list. Is there an easy way to have the most recent appear at the top of the list instead?
I tried:
Template.list.aphorisms = function () {
return Aphorisms.find({}, {sort: {$natural:1}});
};
And am stumped because the Meteor docs don't have many examples.
Assuming that the date_created is in a valid date format along with the timestamp, You should insert the parsed value of date_created using Date.parse() javascript function, which gives the number of milliseconds between January 1, 1970 and date value contained in date_created.
As a result of that, the most recently added record will contain greater value of date_created than the record inserted before it.
Now when fetching the records, sort the cursor in descending order of the date_created parameter as:
Aphorisms.find({}, {sort: {date_created: -1}});
This will sort records from newer to older.
I've found the following to be a cleaner solution:
Template.list.aphorisms = function () {
return Aphorisms.find().fetch().reverse();
};
Given that entire collection already exists in the reverse order that you would like, you can simply create an array of all the objects and reverse the order.
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.