I just started using Sails.js with its ORM, Waterline, and absolutely love it, but I am not sure how to use query modifiers for dates. I am using sails-mysql. Specifically, I am trying to get rows that have a datetime field between two specific dates. I have tried doing this:
MyModel.find()
.where({ datetime_field: { '>=': startDate } })
.where({ datetime_field: { '<=': endDate } })
.done(function(err, objects){
// ...
});
startDate and endDate are two Date objects. I have also tried converting them to strings with toString(). In both cases, I get every row from the database instead of rows between the two dates. Is there a way to do this or is this functionality not yet part of either Waterline or sails-mysql?
In the same boat (no pun intended) but using sails-mongo.
Provided you have the correct date formatting (as Jeremie mentions). I personally store dates in UTC moment(startDate).toISOString() on the client you can moment(startDate) to work in local date and time.
Looking at the Waterline source for deferred queries (see the where method) it applies the most recent datetime_field criteria it finds to be valid.
After trawling through code, searches and the group I didn't find anything that helped. I sure hope I've missed something obvious, but for now my current suggestion would be to anchor the results on your startDate and then cap it with a limit,
e.g.
.where({ datetime_field: { '>=': startDate } })
.limit(100)
You will need to format your date as a string in the YYYY-MM-DD format.
If you need help formatting your dates, moment.js has a lot of cool features for that.
formating your date would look something like
var formatedStartDate = moment(startDate).format('YYYY-MM-DD');
Related
Time in mysql is stored like this
2022-04-25 11:03:20
but when it is showed on client with vuejs i am getting this as response
2022-04-25T09:03:20.000Z
How do i show it as it is shown in db?
The date you're getting is in ISO-8601 format. You'll want to continue to store it like that so you've got the timezone (as denoted by the suffix 'Z'). In your frontend, it's easy to convert the date into any format you like.
For example, based on your example, you can use:
const dateFromDb = '2022-04-25T09:03:20.000Z';
const dateForUi = new Date(dateFromDb).toLocaleString('nl-NL');
console.log(dateForUi); // 25-4-2022 10:03:20
You can also convert any date object back into ISO format, using .toISOString().
There's also many other date formatting methods (outlined in the Date() docs), or for more advanced date / time operations there are libraries like moment.js
In my application, a user can specify a date in a form, via a datepicker. Doing so, the date has this format : "2018-05-16T12:45:30Z".
Then, I want to store it in a MySql database, in a TIMESTAMP column.
Later, the user can edit his data. Consequently, the datepicker has to be initialized with the date coming from the server, previously saved.
To manage this, I created an accessor and a mutator :
public function setDateNameInputAttribute($value)
{
$this->attributes['date_name_input'] = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $value);
}
public function getDateNameInputAttribute($value)
{
return Carbon::parse($value)->format('Y-m-d\TH:i:s\Z');
}
This code works fine : my front-end reads UTC (Zulu) dates and I can insert timestamps in my database.
However, it's not perfect.
Let's say I need for whatever reason to add one hour to a stored date
$myObject = MyClass::find(1);
$theDate = $myObject->dateNameInput;
Now $theDate is a "T Z format" string, because of the accessor. I could recreate a Carbon object to do my addition, but I think this Carbon -> string -> Carbon transition would be ugly. How can I make a nice operation ?
If my applications contains a lot of input dates, with many different model names, is there a way to generalize my accessor and my mutator ?
Actually, is my first approach good ?
Thanks for reading !
I'm mapping my JSON responses from the Server side code into an Interface, in this way;
objectFromJson: IMyObject = <IMyObject>jsonData;
The problem is, that the Json contains a Date, is there a way to automatic cast the date to an real Typescript Date without something like this:
new Date(parseInt(incident["CreatedOn"].substr(6)));
that the Json contains a Date, is there a way to automatic cast the date to an real Typescript Date without something like this
Your json seems to create date as a number. BAD IDEA. Reason:
how about dates before 1970
it is unreliable based on time zones
Prefer you return dates as strings. More API recommendations : https://github.com/interagent/http-api-design
If all you have is it returned as number than what you have is okay. Else if you have dates in a JavaScript recommended format e.g. 2012-01-01T12:00:00Z you would do var date = new Date('2012-01-01T12:00:00Z')
Is there a way to force Sequelize use UNIX Timestamp as default time format both for createdAt/updatedAt timestamps and for custom-defined Sequelize.DATE field types?
Thanks!
P.S. I'm using MySQL
At any given moment in time, there are two possible dates (depending on one's position relative to the international date line): that is, converting from a UNIX timestamp to a date requires one to consider the timezone.
For example, the UNIX timestamp 946684800 is 2000-01-01 00:00:00Z. Whilst this represents the first day of the new millenium pretty much everywhere east of the Atlantic, it's still millenium eve everywhere to the west of that ocean. So which date does it represent?
Whilst it's possible to convert from a date to a timestamp, one must define one's own convention for so doing (e.g. represent a given date as midnight in UTC) or else the same date may be represented differently upon each encoding. Generally speaking, this is a bad idea which may have all sorts of unintended consequences.
There is a reason that the DATE data type exists: it is the correct way to store a date. Use it.
While eggyal's answer is the proper way to do things in MySQL, some of us might be working in an environment or team that requires us to use a unix timestamp instead of a datetime / timestamp.
I found that a great way to accomplish this is to use hooks inside of sequelize. At the bottom of each of your models, you can add this code:
{
tableName: 'Addresses',
hooks : {
beforeCreate : (record, options) => {
record.dataValues.createdAt = Math.floor(Date.now() / 1000);
record.dataValues.updatedAt = Math.floor(Date.now() / 1000);
},
beforeUpdate : (record, options) => {
record.dataValues.updatedAt = Math.floor(Date.now() / 1000);
}
}
}
This will insert the createdAt and updatedAt fields as unix timestamps.
No or at least not yet.
CreatedAt is set using the utils.now function in sequelize. That function uses the javascript Date function with no additional arguments. Squelize could be modified to change the way it calls Date but there is no code to do that in the current version.
see here
You could however disable the createdAt and other timestamps and use raw queries to set your own. However then you're sacrificing the functionality of sequelize.
Best solution is probably to convert those fields to unix time in your business logic before using them.
I have a document in CB which has two dates, a start date and an end date. Let's say, a product's price discount. 10% off starting from today and ends next Friday. How can I get all the documents from CB which have a valid discount today?
I made a view and have the following in it:
var dt = new Date();
Which gets today's date. Then I can do a simple
if(doc.FromDate < dt && doc.ToDate > dt){ emit([ ..... ]);
This filters the documents how I want. But...
Question
Is this a good approach re view and index updating? Will the index update every day because the date changed? Just trying to understand the working of CB in this respect
What is the best approach for this type of searching? If not possible please tell me!
Cheers
Robin
Note: Please note, the question is NOT like this here or this here
Let's me clarify something here:
the map() function is used to create/update the index on disk, and this occurs just "after" the document is saved on disk. This is why using date.now() in the map reduce does not really makes sense.
So what you will do is to emit the date for example emit( dateToArray(doc.startDate) );
then when you query the view(index) you can use the startkey & endkey to do a range query.
&startkey=[2013,4,16]&endkey=[2013,4,24]
the index won't be updated just because system date changed, you have to update the document. also view indexer doesn't allow you to pass any arguments defined by user. in this case you should emit the data and use date as a part of the key to filter on view query. I guess the same behaviour for SQL indexes too. you cannot predict when exactly this document will indexed, in your example you are freezing timestamp when the doc has been indexed, it isn't even the time when it was changed