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);
Related
This is my data format:
"21/03/2019 19:18"
The problem i am facing is, when ever if i am dealing with date or time there is an issue with the month ( it has 03 instead of 3 ). I am using library called date-fns. And also i have tried with the help of javascript date objects without using library, but no luck still the month should not have zero in-front of it.
So, how to remove the "0" in-front of "3", and one more problem is how to do this conditionally , because when its Dec, i will be getting data as "21/12/2019 19:18". So, in this case , i should not remove "1" as its located in same position of "0" in previous scenario.
In other words, i want to remove "0" by checking if there is "1" presented in that position or index, if presented then remove else remove "0"
How to achieve this.
I tried the below code:
const d = new Date(2019,03,21)
But, its says legacy error. So when i removed "0" infront of "3" it works fine. Please help
I assume you get the data back as a string and you just want to remove leading zeros from the 2nd number only?
we can use .split to break up the string into parts, and then we can use parseInt to convert some string parts into numbers. that will turn the string "03" into the number 3
function removeleadingZerosFromDateString(str) {
//Break up the date string on the slashes and whitespace, so we have an array of all the parts
var parts = str.split(/\/|\s/);
console.log(parts);
//Assign each array item to a variable so we can see what is what
var day = parseInt(parts[0], 10);
var month = parseInt(parts[1], 10);
var year = parts[2];
var time = parts[3];
var meridian = parts[4];
return day+'/'+month+'/'+year+' '+time+' '+meridian;
}
var result = removeleadingZerosFromDateString("21/03/2019 19:18 PM");
console.log(result);
You said you were using date-fns, so I'll give an answer in that regard.
The current 1.x version doesn't support parsing strings in a custom format, but they are adding that to 2.x, and you can use the alpha release to try it today.
The syntax is:
var date = parse(dateString, formatString, baseDate, [options]);
See the documentation for the parse function in version 2.0.0-alpha.27.
In your case, it would be like this:
var date = parse("21/03/2019 19:18", "MM/dd/yyyy HH:mm", new Date());
Lastly, if you want to use a library for this but don't want to experiment with an alpha, you can either wait for Date-fns 2.0 to become final, or you can try Luxon or Moment - both of which already have this functionality (though Moment uses a slightly different token format "MM/DD/YYYY HH:mm").
I am trying to compare two dates but always it gives me opposite result.
I am trying to compare below dates
var tocompare=09/22/2017 and var insurenceexpiry=04/02/2018
I tried to compare as below.
console.log(insurenceexpiry > tocompare);
console.log(insurenceexpiry < tocompare);
which gives me false and true. As per my knowledge insurenceexpiry is greater and when i compare as insurenceexpiry > tocompare it should give me true but I am getting false. What I am doing wrong?
You have to convert it into dates using new Date(datestring).
Otherwise 9/22/2017 without quotes will do math operations
var tocompare=new Date("09/22/2017");
var insurenceexpiry=new Date("04/02/2018");
console.log(insurenceexpiry > tocompare);
console.log(insurenceexpiry < tocompare);
If you want to compare 2 dates as string directly, then use YYYY/MM/DD format, (you can use any separator apart from /, the main thing is YYYYMMDD)
Otherwise parse them as date (as per i--'s answer) and then compare, as a month or day can be bigger than another date, but that doesn't meant that it's actually a bigger date, so you cannot use mmddyyyy format for a simple string comparison to get which date is bigger.
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.
Given
var fromDatetime = "10/21/2014 08:00:00";
var toDatetime = "10/21/2014 07:59:59";
Target
Need to compare this two given datetime to check if this is a valid datetime inputs.
Im thinking that I could use this solution. .
var fromDatetime = new date("10/21/2014 08:00:00");
var toDatetime = new date("10/21/2014 07:59:59");
then compare each segment
fromDatetime.getFullYear() to toDatetime.getFullYear(),
fromDatetime.getMonth() to toDatetime.getMonth(),
so on so forth until I get a non equal comparison, then return.
My question is. . Is that the best case in comparing datetime in Javascript?
Any suggested solutions other than this will be much appreciated. .
Thank you in advance.
If you only need to know if one date is before or after another, you can use normal comparison operators:
if (dateA > dateB) { ... }
(Note that to instantiate Date objects, it is new Date(myDateString), not new date() as in your example.)
This works because the Date objects will be coerced to the underlying epoch values, which are just numbers representing the count of milliseconds that have passed since Jan 1, 1970, GMT. (Relational comparison uses the result of the operands’ ##toPrimitive or valueOf() functions if available.) As a result, this will be sensitive down to the millisecond, which may or may not be desired. You can control the granularity of the comparison either by making sure the input only includes values up to the hour/minute/whatever OR by doing piecemeal comparisons like you described in your question.
For more advanced date comparison operations, I highly recommend using a library like Moment.js, because natively there is not much to work with. For example Moment provides methods like
moment(myDateString).startOf('hour')
which can be very helpful if you need to make comparisons only at a particular level of specificity. But none of the datetime libraries are terribly lightweight, so only use them if you are either doing serverside code or you expect to rely on them extensively. If you only need to do this one comparison, it will be wiser to roll your own solution.
When writing a new date object with a string, one can write it as:
var someDay = new Date("12/01/2012");
This equals December 1st 2012.
However, what if the user has to fill in a date on a website where the format isn't month/day/year, but day/month/year? How would one go about creating a date object with the correct date then?
If you are getting the data as a string from another website, then you need to know the format in which that website provides you the date. There is no way around this because D-M-Y and M-D-Y are indistinguishable; even Y-M-D would be indistinguishable if they used a two-digit format for the year.
This hasn't been tested at all, but at worst the general idea should solve your problem.
var pattern = /^(\d+)\b(\d+)\b(\d+)$/;
if (!pattern.test(dateString))
return null;
var matches = dateString.match(pattern);
if (siteUsesDMY)
return new Date(matches[2], matches[1]-1, matches[0]);
if (siteUsesMDY)
return new Date(matches[2], matches[0]-1, matches[1]);
...
Pattern: This pattern supports any numeric representation of the date, assuming it has a breaking character between each unit. If you need to support a website that doesn't have a breaking character, you would need a different pattern that matched that website's exact format (i.e.: site sends DDMMYYYY, then pattern would be /^(\d{2})(\d{2})(\d{4})$/).
Also fixed the month parameter in date creation, as I just remembered that JavaScript uses 0-11 for months.