Timestamp with nodejs and mongoose - javascript

I am learning nodeJS now, so I did this tutorial( http://scotch.io/tutorials/javascript/creating-a-single-page-todo-app-with-node-and-angular) , and now I want add timestamp with each todo.
I create a simple file(time.js) with moment.js
var moment = require('moment');
moment().format();
var mytime = moment().format('MMMM Do YYYY, h:mm:ss a');
module.exports = {
time : mytime
}
And connect it to my routes file
var qtime = require('./time');
app.post('/api/todos', function(req, res) {
...
Todo.create({
....
time : qtime.time}
....
Here I get my server startup time, not the time when I POST(thats what I need)
Here the out
"time": "February 21st 2014, 12:00:40 pm",
"time": "February 21st 2014, 12:00:40 pm",
"time": "February 21st 2014, 12:00:40 pm",
...
How to get current time on each request?

There is function that mongoose schema exposes for you that handles default values. These default values can be calculated ones. In this example, the right and easy way to achieve what you ask here is as follows
new Schema({
date: { type: Date, default: Date.now }
})
When you save the object, you do not need to specify the "date" field anymore, mongoose will take care of it!
Mongoose Docs: http://mongoosejs.com/docs/2.7.x/docs/defaults.html (old)
http://mongoosejs.com/docs/schematypes.html (current version)

Why go through all that extra work instead of defining your time field in your schema to be of type Date and use middleware to set?
var todoSchema = mongoose.Schema({
time: Date
});
todoSchema.pre('save', function (next) {
if (!this.isNew) next();
this.time = new Date();
next();
});

Related

How to create a Timestamp and Geopoint instance in Firebase Emulator from browser console

I have create a mock data and performed a batch update with firestore.batch(). The problem is that location is saved as a number and time as a string and not as Geopoint and Timestamp instances respectively, causing my React app to crash.
I could see that only firestore is accessible through window.firestore, but not Firebase. Since Firebase isn't exported as window.firebase, I cannot create either Geopoint or Timestamp instance.
So, how to create a Timestamp and Geopoint instance in Firebase Emulator from browser console?
Here's a type of doc I'm adding to firestore
const doc = {
"company": "company-1",
"location": [
-72.3623, // number
79.5748 // but, want to convert to Geopoint instance
],
"time": "Fri Sep 10 1976 07:42:23 GMT+0530 (India Standard Time)", // string
"createdAt": "Mon Apr 28 2014 13:30:16 GMT+0530 (India Standard Time)", // want to convert to Timestamp
}
A more dependable accessor path than .Gf:
new firestore.app.firebase_.firestore.GeoPoint(lat, lng)
There's a firebase accessible through window.firestore.
So I figured a way to create Geopoint and Timestamp instance through Firestore.
You can access it through window.firestore.Gf.firebase_, through which you can create those both instance.
const raw = // pasting from clipboard
const batch = firestore.batch()
const firebase = firestore.Gf.firebase_
const Timestamp = firebase.firestore.FieldValue().Timestamp
const GeoPoint = firebase.firestore.FieldValue().GeoPoint
raw.forEach(doc => {
const docRef = firestore
.collection('user')
.doc('user-1')
.collection('interviews')
.doc()
doc = {
...doc,
time: Timestamp.fromDate(new Date(doc.time)),
createdAt: Timestamp.fromDate(new Date(doc.createdAt)),
location: new GeoPoint(doc.location[0], doc.location[1])
}
batch.set(docRef, doc)
})
batch.commit()

Mongoose not returning the correct number of results

I'm new to mongoose. I'm trying to query by createdAt date, with startDate and endDate, however I got the incorrect number of results.
data
{"_id":{"$oid":"5f4fab9beceaa20f898feafb"},"message":"Inquiry 101","service":"GENERAL_INQUIRY","name":"Alex","email":"alex#gmail.com","personalNumber":"0991898838398","createdAt":{"$date":"2020-09-02T14:26:35.237Z"},"updatedAt":{"$date":"2020-09-02T14:26:35.237Z"}}
{"_id":{"$oid":"5f4fc3677e7b1e2d806714cf"},"message":"Inquiry 101","service":"GENERAL_INQUIRY","name":"Joshua","email":"joshua#gmail.com","personalNumber":"0991898838398","createdAt":{"$date":"2020-09-02T16:08:07.123Z"},"updatedAt":{"$date":"2020-09-02T16:08:07.123Z"}}
{"_id":{"$oid":"5f50b80f28ca26065b2ac9a5"},"message":"Inquiry 101","service":"GENERAL_INQUIRY","name":"Harold","email":"harold#gmail.com","personalNumber":"0991898838398","createdAt":{"$date":"2020-09-03T09:31:59.112Z"},"updatedAt":{"$date":"2020-09-03T09:31:59.112Z"}}
{"_id":{"$oid":"5f59104ff518c40579b578d0"},"message":"Inquiry 101","service":"GENERAL_INQUIRY","name":"Katy","email":"katy#gmail.com","personalNumber":"0991898838398","createdAt":{"$date":"2020-09-09T17:26:39.787Z"},"updatedAt":{"$date":"2020-09-09T17:26:39.787Z"}}
I have 4 records with the ff. date 2020-09-02, 2020-09-03 and 2020-09-09
I wanted to get all records from 2020-09-02 and 2020-09-03, with these I expected 3 results as I have to records on the 2020-09-02, however I only got 2 results, those records have 2020-09-02 date with them.
const { limit = 30 } = params;
return new Promise((resolve, reject) => {
const query = {
createdAt: {
$gte: '2020-09-02',
$lte: '2020-09-03',
}
};
this.model.find(query).sort({
createdAt: 'descending',
}).limit(limit).exec((err, res) => {
if (!err) {
resolve(res);
}
reject(err);
})
})
Did I miss something with my code?
I also tried passing new Date('2020-09-02') but I still got same results.
I tried setting mongoose debug to true and below is what I got.
Mongoose: inquiries.find({ createdAt: { '$gte': new Date("Wed, 02
Sep 2020 00:00:00 GMT"), '$lte': new Date("Thu, 03 Sep 2020 00:00:00 GMT") }}, { sort: { createdAt: -1 }, limit: 30, projection: {}
})
Thanks in advance.
Youre looking for records greater than 2020-09-02 00:00:00 and less than 2020-09-03 00:00:00.
You only have 2 records which are between these values, if you want records including those at 2020-09-03 23:59:59, set your lte to 2020-09-04

Knex returns DATETIME fields applying offset of my machine timezone

I have following row saved in timezone Europe/Madrid at database:
dateA = '2019-03-26 15:00:00'
dateB = '2019-03-26 14:00:00'
When selecting the entry:
let entry = this.query().findById(id)
I get following values (console.log(entry)):
{
dateA: 2019-03-26T06:00:00.000Z,
dateB: 2019-03-26T05:00:00.000Z
}
What is applying this convertion?
My enviroment:
Im using knex, objection and moment
Moment is configured with moment.tz.setDefault('Europe/Madrid')
My local machine timezone is set to UTC+09:00 (Chita) for testing
I tried:
Setting a connection timezone on knex creation:
const connection = {
user: dbCreds.username,
password: dbCreds.password,
host: hostname,
database: dbCreds.database,
timezone: '-1:00'
}
const pool = knex({
client: 'mysql2',
connection,
pool: {
min: 2,
max: 30
}
})
I still get the same result
Finally found out whats going on.
Knex, when retrieving the info of the datetime field checks the timezone of the database. You can check it using:
SELECT ##global.time_zone, ##session.time_zone;
This returns SYSTEM SYSTEM in my case. So its using my machine timezone. To test it, I changed it to UTC.
So now, when reading the following value:
dateA = '2019-03-26 15:00:00'
dateB = '2019-03-26 14:00:00'
Knex assumes its in UTC, so the value in UTC is returned:
{
dateA: 2019-03-26T15:00:00.000Z,
dateB: 2019-03-26T14:00:00.000Z
}
Seems not possible to configure MySQL to use 'Europe/Madrid' as default timezone.

How to query for date ignoring its time in ISODate value [duplicate]

I've been playing around storing tweets inside mongodb, each object looks like this:
{
"_id" : ObjectId("4c02c58de500fe1be1000005"),
"contributors" : null,
"text" : "Hello world",
"user" : {
"following" : null,
"followers_count" : 5,
"utc_offset" : null,
"location" : "",
"profile_text_color" : "000000",
"friends_count" : 11,
"profile_link_color" : "0000ff",
"verified" : false,
"protected" : false,
"url" : null,
"contributors_enabled" : false,
"created_at" : "Sun May 30 18:47:06 +0000 2010",
"geo_enabled" : false,
"profile_sidebar_border_color" : "87bc44",
"statuses_count" : 13,
"favourites_count" : 0,
"description" : "",
"notifications" : null,
"profile_background_tile" : false,
"lang" : "en",
"id" : 149978111,
"time_zone" : null,
"profile_sidebar_fill_color" : "e0ff92"
},
"geo" : null,
"coordinates" : null,
"in_reply_to_user_id" : 149183152,
"place" : null,
"created_at" : "Sun May 30 20:07:35 +0000 2010",
"source" : "web",
"in_reply_to_status_id" : {
"floatApprox" : 15061797850
},
"truncated" : false,
"favorited" : false,
"id" : {
"floatApprox" : 15061838001
}
How would I write a query which checks the created_at and finds all objects between 18:47 and 19:00? Do I need to update my documents so the dates are stored in a specific format?
Querying for a Date Range (Specific Month or Day) in the MongoDB Cookbook has a very good explanation on the matter, but below is something I tried out myself and it seems to work.
items.save({
name: "example",
created_at: ISODate("2010-04-30T00:00:00.000Z")
})
items.find({
created_at: {
$gte: ISODate("2010-04-29T00:00:00.000Z"),
$lt: ISODate("2010-05-01T00:00:00.000Z")
}
})
=> { "_id" : ObjectId("4c0791e2b9ec877893f3363b"), "name" : "example", "created_at" : "Sun May 30 2010 00:00:00 GMT+0300 (EEST)" }
Based on my experiments you will need to serialize your dates into a format that MongoDB supports, because the following gave undesired search results.
items.save({
name: "example",
created_at: "Sun May 30 18.49:00 +0000 2010"
})
items.find({
created_at: {
$gte:"Mon May 30 18:47:00 +0000 2015",
$lt: "Sun May 30 20:40:36 +0000 2010"
}
})
=> { "_id" : ObjectId("4c079123b9ec877893f33638"), "name" : "example", "created_at" : "Sun May 30 18.49:00 +0000 2010" }
In the second example no results were expected, but there was still one gotten. This is because a basic string comparison is done.
To clarify. What is important to know is that:
Yes, you have to pass a Javascript Date object.
Yes, it has to be ISODate friendly
Yes, from my experience getting this to work, you need to manipulate the date to ISO
Yes, working with dates is generally always a tedious process, and mongo is no exception
Here is a working snippet of code, where we do a little bit of date manipulation to ensure Mongo (here i am using mongoose module and want results for rows whose date attribute is less than (before) the date given as myDate param) can handle it correctly:
var inputDate = new Date(myDate.toISOString());
MyModel.find({
'date': { $lte: inputDate }
})
Python and pymongo
Finding objects between two dates in Python with pymongo in collection posts (based on the tutorial):
from_date = datetime.datetime(2010, 12, 31, 12, 30, 30, 125000)
to_date = datetime.datetime(2011, 12, 31, 12, 30, 30, 125000)
for post in posts.find({"date": {"$gte": from_date, "$lt": to_date}}):
print(post)
Where {"$gte": from_date, "$lt": to_date} specifies the range in terms of datetime.datetime types.
db.collection.find({"createdDate":{$gte:new ISODate("2017-04-14T23:59:59Z"),$lte:new ISODate("2017-04-15T23:59:59Z")}}).count();
Replace collection with name of collection you want to execute query
MongoDB actually stores the millis of a date as an int(64), as prescribed by http://bsonspec.org/#/specification
However, it can get pretty confusing when you retrieve dates as the client driver will instantiate a date object with its own local timezone. The JavaScript driver in the mongo console will certainly do this.
So, if you care about your timezones, then make sure you know what it's supposed to be when you get it back. This shouldn't matter so much for the queries, as it will still equate to the same int(64), regardless of what timezone your date object is in (I hope). But I'd definitely make queries with actual date objects (not strings) and let the driver do its thing.
Use this code to find the record between two dates using $gte and $lt:
db.CollectionName.find({"whenCreated": {
'$gte': ISODate("2018-03-06T13:10:40.294Z"),
'$lt': ISODate("2018-05-06T13:10:40.294Z")
}});
Using with Moment.js and Comparison Query Operators
var today = moment().startOf('day');
// "2018-12-05T00:00:00.00
var tomorrow = moment(today).endOf('day');
// ("2018-12-05T23:59:59.999
Example.find(
{
// find in today
created: { '$gte': today, '$lte': tomorrow }
// Or greater than 5 days
// created: { $lt: moment().add(-5, 'days') },
}), function (err, docs) { ... });
db.collection.find({$and:
[
{date_time:{$gt:ISODate("2020-06-01T00:00:00.000Z")}},
{date_time:{$lt:ISODate("2020-06-30T00:00:00.000Z")}}
]
})
##In case you are making the query directly from your application ##
db.collection.find({$and:
[
{date_time:{$gt:"2020-06-01T00:00:00.000Z"}},
{date_time:{$lt:"2020-06-30T00:00:00.000Z"}}
]
})
You can also check this out. If you are using this method, then use the parse function to get values from Mongo Database:
db.getCollection('user').find({
createdOn: {
$gt: ISODate("2020-01-01T00:00:00.000Z"),
$lt: ISODate("2020-03-01T00:00:00.000Z")
}
})
Save created_at date in ISO Date Format then use $gte and $lte.
db.connection.find({
created_at: {
$gte: ISODate("2010-05-30T18:47:00.000Z"),
$lte: ISODate("2010-05-30T19:00:00.000Z")
}
})
use $gte and $lte to find between date data's in mongodb
var tomorrowDate = moment(new Date()).add(1, 'days').format("YYYY-MM-DD");
db.collection.find({"plannedDeliveryDate":{ $gte: new Date(tomorrowDate +"T00:00:00.000Z"),$lte: new Date(tomorrowDate + "T23:59:59.999Z")}})
mongoose.model('ModelName').aggregate([
{
$match: {
userId: mongoose.Types.ObjectId(userId)
}
},
{
$project: {
dataList: {
$filter: {
input: "$dataList",
as: "item",
cond: {
$and: [
{
$gte: [ "$$item.dateTime", new Date(`2017-01-01T00:00:00.000Z`) ]
},
{
$lte: [ "$$item.dateTime", new Date(`2019-12-01T00:00:00.000Z`) ]
},
]
}
}
}
}
}
])
For those using Make (formerly Integromat) and MongoDB:
I was struggling to find the right way to query all records between two dates. In the end, all I had to do was to remove ISODate as suggested in some of the solutions here.
So the full code would be:
"created": {
"$gte": "2016-01-01T00:00:00.000Z",
"$lt": "2017-01-01T00:00:00.000Z"
}
This article helped me achieve my goal.
UPDATE
Another way to achieve the above code in Make (formerly Integromat) would be to use the parseDate function. So the code below will return the same result as the one above :
"created": {
"$gte": "{{parseDate("2016-01-01"; "YYYY-MM-DD")}}",
"$lt": "{{parseDate("2017-01-01"; "YYYY-MM-DD")}}"
}
⚠️ Be sure to wrap {{parseDate("2017-01-01"; "YYYY-MM-DD")}} between quotation marks.
Convert your dates to GMT timezone as you're stuffing them into Mongo. That way there's never a timezone issue. Then just do the math on the twitter/timezone field when you pull the data back out for presentation.
Why not convert the string to an integer of the form YYYYMMDDHHMMSS? Each increment of time would then create a larger integer, and you can filter on the integers instead of worrying about converting to ISO time.
Scala:
With joda DateTime and BSON syntax (reactivemongo):
val queryDateRangeForOneField = (start: DateTime, end: DateTime) =>
BSONDocument(
"created_at" -> BSONDocument(
"$gte" -> BSONDateTime(start.millisOfDay().withMinimumValue().getMillis),
"$lte" -> BSONDateTime(end.millisOfDay().withMaximumValue().getMillis)),
)
where millisOfDay().withMinimumValue() for "2021-09-08T06:42:51.697Z" will be "2021-09-08T00:00:00.000Z"
and
where millisOfDay(). withMaximumValue() for "2021-09-08T06:42:51.697Z" will be "2021-09-08T23:59:99.999Z"
i tried in this model as per my requirements i need to store a date when ever a object is created later i want to retrieve all the records (documents ) between two dates
in my html file
i was using the following format mm/dd/yyyy
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script>
//jquery
$(document).ready(function(){
$("#select_date").click(function() {
$.ajax({
type: "post",
url: "xxx",
datatype: "html",
data: $("#period").serialize(),
success: function(data){
alert(data);
} ,//success
}); //event triggered
});//ajax
});//jquery
</script>
<title></title>
</head>
<body>
<form id="period" name='period'>
from <input id="selecteddate" name="selecteddate1" type="text"> to
<input id="select_date" type="button" value="selected">
</form>
</body>
</html>
in my py (python) file i converted it into "iso fomate"
in following way
date_str1 = request.POST["SelectedDate1"]
SelectedDate1 = datetime.datetime.strptime(date_str1, '%m/%d/%Y').isoformat()
and saved in my dbmongo collection with "SelectedDate" as field in my collection
to retrieve data or documents between to 2 dates i used following query
db.collection.find( "SelectedDate": {'$gte': SelectedDate1,'$lt': SelectedDate2}})

accessing mongodb's object from mapper (MapReduce)

I have an extra question based on the one I asked before:
calculate frequency using mongodb aggregate framework
so my data in MongoDB looks like this now:
{
"data": {
"interaction": {
"created_at": "Wed, 09 Apr 2014 14:38:16 +0000"
}
},
"_id": {
"$oid": "53455b59edcd5e4e3fdd4ebb"
}
}
before I used to have it like:
[
{
created_at: "2014-03-31T22:30:48.000Z",
id: 450762158586880000,
_id: "5339ec9808eb125965f2eae1"
}
]
so to access created_at I was using mapper like:
var mapper = function () {
if ( this.created_at.getTime() > ( last_date + 10000 ) ) {
...
but as the structure in my database has changed, I tried to change:
this.created_at.getTime()
to:
this.data.interaction.created_at.getTime()
but unfortunately it didn't work out. Thank you for any help
Hate to make this that simple but all you want to do when importing these date strings is this:
new Date("Wed, 09 Apr 2014 14:38:16 +0000")
Which will return a proper date type that you actually should be inserting as part of your data.

Categories