So, I just had a big "Oh Snap!" moment.
I'm using MomentJS with AngularJS and IndexedDB in an offline app.
All my records are stored with an index date_idx based on the date property of the object.
The problem comes when I try to run queries based on the date using the following code:
$scope.redoresults = function(){
$indexedDB.openStore('records', function(store){
$scope.upper = moment($scope.dates.endDate).format("DD[/]MM[/]YYYY");
$scope.downer = moment($scope.dates.startDate).format("DD[/]MM[/]YYYY");
var find = store.query();
find = find.$between($scope.downer, $scope.upper, false, false);
find = find.$index("date_idx");
store.eachWhere(find).then(function(e){
$scope.daterange = e;
console.log($scope.daterange);
});
});
};
The query was delivering weird results, sometimes correct, sometimes not.
Until I realized that I'm actually querying against strings, not dates.
Being so, a query between 01/08/2016 and 31/08/2016, will still deliver me results containing 20/09/2016, because as a number it's indeed between the range.
I feel I'm missing something structure-wise.
Any comment on how to solve this issue?
Should I query against some other index? But then how can I compare the dates?
Store dates as dates, and query using dates.
Or, store dates as timestamps (e.g. date.getTime()), and then query using timestamps
Do not store dates as dates and then query with a string date, this will produce junk.
Do not store dates as strings, and then query with a string date, this will produce junk. String values are compared lexicographically which can easily depart from how dates are compared.
Related
If I had an array of dates, is there a way I could match up another date by rounding up until one is matched?
For example, say I have an array of dates:
"2022-09-15"
"2022-10-10"
"2022-12-01"
And I have a date pulled from the application: "2022-09-29", I want the date to update itself by rounding up until the next upcoming date ("2022-10-10") is selected.
I am unsure how I would round up like I could in mathematics situations.
Assuming your dates are in order, you can iterate through your array starting at the beginning until you find the first date that is bigger than you date provided by the application. In JavaScript, your can do a direct comparison like this:
"2022-09-15" > "2022-10-10" // false
"2022-09-15" < "2022-10-10" // true
Note that this works because of the ordering of the year, month, and day that you have presented. If you wanted to do comparisons where you had day, month, year, you would want to create a Date JavaScript object and do the comparisons that way. You can read more about those here: Compare two dates with JavaScript
But for your use case, a simple loop could look like this:
for(let i = 0; i < array.length; i++) {
if(applicationDate < array[i])
return array[i]
}
You don't necessarily need to "round" the dates up. Incrementing the date and comparing it to every entry in the array until you find a match would take a relatively large amount of time and resources. I prefer a kind of "knock-out" approach to problems like this. Simply rule out everything it can't be until you're left with a single option. In this case, since you specifically need a date that comes after the input date, we can first rule out anything before the input date. We can then take this new list of dates (that we now know are all after the input date) and get the "smallest" one. This will effectively give you the date that is closest to the input date but still after it.
In your question you presented the dates as a list of strings. This isn't a huge deal because this can still be fairly easily accomplished, but the strings must be in a format that JavaScript recognizes as a date, otherwise all comparisons will result in false. Here is a list of the valid date formats.
I personally like to avoid depending on the order of arrays just because it can be hard to maintain and if/when it breaks, it's generally very hard to find that the issue is that the array is out of order (speaking from experience here). For this reason, the code examples provided here will be completely unreliant on the order of the array.
First, let's discuss a solution using Date objects. This is fairly straight forward. The only thing is that you would need to make sure the date being input is in a valid format as discussed previously. Keep in mind the input needs to be converted to a Date object (if it isn't already) because comparisons between date strings and Date objects always return false. To get only dates after the current date, we can use Array.prototype.filter(), and to get the "smallest" date afterwards we can use Math.min.apply() as explained in this Stack Overflow answer.
var dates = [
new Date("2022-09-15"),
new Date("2022-10-10"),
new Date("2022-12-01")
];
var inputDate = new Date("2022-09-29");
var datesAfter = dates.filter(x => x > inputDate);
var closestDate = new Date(Math.min.apply(null,datesAfter));
console.log(closestDate);
Now for date strings. The idea is largely the same as Date objects. The only difference really is that we can't use Math.min.apply() on date strings. We can however use Array.prototype.reduce() in order to compare all the dates, it's just a bit more involved.
var dates = [
"2022-09-15",
"2022-10-10",
"2022-12-01"
];
var inputDate = "2022-09-29";
var datesAfter = dates.filter(x => x > inputDate);
var closestDate = dates.reduce((a, b) => a > b ? a : b);
console.log(closestDate);
I have some entries in a database and and they all contain a date string.
I have some TS like this
ref.LimitToFirst(10).orderByChild('date')
The problem i an having is that TS treats this as a regular string and just orders by the first number in the date. ex - 10/1/2021 would be ordered before 2/1/2021. How could i fix that ?
You can't fix this in code while depending on the database to perform the query. In Realtime Database, strings will always sort lexicographically - by their natural string order. You can't make it interpret the strings as something other than a normal string.
You will have to instead store an integer value that you can sort chronologically. In JavaScript, you can simply create a Date object and use its getTime() method field to get the Date's representation in millis since the unix epoch.
If you can't store a proper timestamp, then your only option is to read all the data and sort it yourself in your app, which will not scale well.
This question already has answers here:
Convert .NET date format into JavaScript date
(1 answer)
Parsing a Auto-Generated .NET Date Object with Javascript/JQuery
(2 answers)
Closed 2 years ago.
I'm attempting to convert a Date that is returning from the database as /Date(1570474808430)/. I'd like to convert it as a standard date time result such as it's appearing in the database as : 2020-08-04 11:08:22.630. Is this something that is possible? I'm not entirely sure why it appears as date time in the database but is returning as /Date(1570474808430)/ on the front end.
I've attempted to approach this with the following code:
let oldDate = /Date(1570474808430)/
let updatedDate = new Date(oldDate);
console.log(updatedDate)
My expected result is to convert /Date(1570474808430)/ to a date time: 2020-08-04 11:08:22.630
Your snippet, perhaps unknown to you, actually tries to pass a regular expression literal to the Date constructor. What comes back from your API is actually a string - of the form /Date(xxx)/ where xxx appears to be a Unix timestamp. In order to translate this to a Javascript date object, we need to parse the timestamp out of that - assuming the data always has this format - and ironically, the simplest way to do that is probably a regular expression:
const oldDate = "/Date(1570474808430)/";
const timeStamp = Number(oldDate.match(/\/Date\((\d+)\)\//)[1]);
const updatedDate = new Date(timeStamp);
console.log(updatedDate)
This works if you can guarantee your data will be in this form - but frankly it is not good code, and will certainly lead to problems if your data isn't always in this format. The best thing you could do, if it's possible, would be to update your data so that it holds a sensible date-string in a standard format. Or failing that, at least a number representing the Unix timestamp, without the /Date(...)/ cruft.
I'm trying to scan a table and return all entries which match my filter expression. I've got an API Gateway which accepts a GET-Request that contains a starting time and a end time. (Format: [dd.mm.yyyy hh:mm:ss]
The database im scanning has an attribute called "timestamp" in the same format. I've tried it with the filter
Timestamp BETWEEN :date1 and :date2
date1 and date2 represent the starting and ending time from the API. Timestamp is the field in my Database.
Unfortunately the scan doesnt return any values.
Thanks a lot.
Your date format has to be in ISO 8601 string format for you to be able to scan on it. You can see this in the documentation here, under the "String" category.
I am building a web page which pulls videos from both YouTube and Vimeo, creates thumbnails for them, and should then sort the thumbnails by date. I currently am querying the vVimeo album API endpoint and the YouTube data API - which both return dates for videos in a slightly different manner.
YouTube DATE: 2012-12-20T08:00:40.000Z
VIMEO DATE: 2013-01-02 13:33:51
My question is, how do I get these two different formats into a singular format that I can then sort with JavaScript / jQuery? I'm assuming if I manage to strip the dashes, spaces, and colons, remove the "t" and "z" in the YouTube date, I'll have an actual number which could be sorted - but it seems a little janky, and I'm hoping there is a better way to format these. Anyone have any ideas?
I would convert the dates to an Javascript Date object, then getTime() from the instance, to sort it.
Let's do an example:
var dates = [];
dates.push(new Date('2013-01-02 13:33:51'));
dates.push(new Date('2012-12-20T08:00:40.000Z'));
Now you have an array with 2 dates you want to sort. Let's do it!
function sortByDate(a, b) {
return a.getTime() - b.getTime();
}
dates.sort(sortByDate);
If you want a descendent sort, just invert a and b:
function sortByDate(a, b) {
return b.getTime() - a.getTime();
}
After you can check your array has sorted doing a console.log(dates).
So for the answer the question, you just need to convert the date string in a Date object, then you will be able to compare to sort.
Troubles with Internet Explorer, check this:
Javascript Dates in IE nan, Firefox and Chrome ok
Problem with Javascript Date function in IE 7 returns NaN
Updated:
However, if you plan to have any browser compatibility, you can use advanced browsers date converter, like this project: JS Date Format
Just parse the date into the number of milliseconds since January 1, 1970. That's what JavaScript uses.