MomentJS range not always including current month in date range - javascript

For some odd reason, MomentJS range does not always display the current month. I am wondering if there is an option that needs to be set so that it includes the current month in it's date range.
This is the code used to generate the date range. I've also attached a codepen so you can see it in action.
http://codepen.io/anon/pen/rORmxY
//momentJs creates the ranges
//Only shows April 2015
var end = moment("2015-05-01","YYYY-MM-DD");
//where the day is > 18 it Shows May 2015
var end2 = moment("2015-05-19","YYYY-MM-DD");
var start = moment().subtract(1.5, "year");
var range = moment.range(start, end);
var range2 = moment.range(start, end2);
//iterate through the months, and populate the SELECT box
range.by('months', function(date) {
//add those values to a SELECT box
$('#month-range').prepend($('<option>', {
value: date.format("MMM YYYY"),
text: date.format("MMM YYYY")
}));
});
//iterate through the months, and populate the SELECT box
range2.by('months', function(date) {
//add those values to a SELECT box
$('#month-range2').prepend($('<option>', {
value: date.format("MMM YYYY"),
text: date.format("MMM YYYY")
}));
});
Thanks a lot

The work around I've found is to simply tell momentJs to use the end of the month for the range. Which makes sense in this context. This is done by adding .endOf("month") to the end range.
See this code for clarification:
//momentJs creates the ranges
//adding .endOf("month") will Include the month of May in the month ranges
var end = moment("2015-05-01","YYYY-MM-DD").endOf("month");
var start = moment().subtract(1.5, "year");
var range = moment.range(start, end);
//iterate through the months, and populate the SELECT box
range.by('months', function(date) {
//add those values to a SELECT box
$('#month-range').prepend($('<option>', {
value: date.format("MMM YYYY"),
text: date.format("MMM YYYY")
}));
});
Thanks a lot for the help

Please take a look at the source code of month-range (https://github.com/gf3/moment-range/blob/master/lib/moment-range.js).
The reason that setting end date to 2015-05-18 will include one less month as 2015-05-19 is nothing special. It is because today is 2015-11-18 and you set the start date to be 2014-05-18.
Now look at _byString function in moment-range (which is called by 'by' function).
function _byString(interval, hollaback, exclusive) {
var current = moment(this.start);
while (this.contains(current, exclusive)) {
hollaback.call(this, current.clone());
current.add(1, interval);
}
}
'current' variable starts from '2014-05-18' and increases one month at a time.
If the end date is 2015-05-19, 'this.contains()' simply returns true when 'current' = '2015-05-18'. And if end date is 2015-05-19, 'this.contains' will return false. This is the reason for the behavior of your code.
Now, if you wanna always include the current month, I think you always add 1 day to the end date. However, I image this method might cause some problem for the last day of a month. Or you can always set the end date to the first day of the next month, but exclude that month. You can do some experimentation.
Hope this helps!

Related

Why can't I pre-select current month on select drop-down element when I can on a year drop-down?

I'm using a jquery third party plugin (https://github.com/NickBusey/jQuery-Date-Select-Boxes-Plugin) that pre-populates select elements with year, month, and day. It lists the correct number of days for each month, taking leap year into account.
When the page loads, this script creates the select elements, as expected.
What I want to do after that is pre-select the current month and day so the user doesn't have to always start with January 1.
I have been successful in changing the year, but similar code has no effect on the month and day selects.
Here are the functions for changing the year and the month:
function preset_year_select( element ) {
var year = get_target_year(); // separate function that returns the year
$(element).filter(function() {
return $(this).text() == year;
}).prop('selected', true);
}
function preset_month_select( element ) {
var today = new Date();
var monthname = get_month_name(today); // separate function that returns the month name
$(element).filter(function() {
return $(this).text() == monthname;
}).prop('selected', true);
}
These selects are in a bootstrap modal. I call these functions when the modal is opened:
preset_year_select( $('#pto-entry-form--date-year option') );
preset_month_select( $('#pto-entry-form--date-month option') );
I'm getting no errors or anything. I can see that the filter is working on the month if I console.log the output. It will return true on the correct month. It just doesn't set the selected property as the year function does.
Any ideas what I might be missing?

Moment check next month

I'd like to check the date if it's next month from the current.
Some test cases here
2020.1.1 2019.12.30 // true
2019.11.30 2019.10.10 // true
2019.12.11 2019.12.1 // false
So as you can see, I'd like to check if the date is next month from now.
Hope to get the brilliant idea!
Best
Kinji
You could try this approach, we have to handle the case when the dates are in the same year and also for December and January of the next year.
A simple algorithm can be created, whereby we multiply the year by 12, add the month and get the difference of this score between the two dates. As long as the value of this is 1 or -1 we have months that are adjacent. I'm presuming you only need to check if the first parameter is the next month to the second parameter, so we check for a difference of 1.
function isNextMonth(timeStamp1, timeStamp2, format = "YYYY.MM.DD") {
let dt1 = moment(timeStamp1, format);
let dt2 = moment(timeStamp2, format);
return ((dt1.year()*12 + dt1.month() - dt2.year()*12 - dt2.month()) === 1);
}
let inputs = [['2020.1.1','2019.12.30'],['2019.11.30', '2019.10.10'], ['2019.12.11','2019.12.1'], ['2020.12.1','2021.1.1'], ['2020.6.1','2020.5.1'], ['2021.1.1','2019.12.1'], ['2019.3.1', '2019.4.1']];
for(let [inputa, inputb] of inputs) {
console.log(`isNextMonth(${inputa}, ${inputb}): ${isNextMonth(inputa, inputb)}`);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
A very simple solution would be to use Moment’s isSame. This only checks the month. If you also want to make sure that the year matches you would have to make sure that nextMonth.getYear() matches dateToCheck.getYear()
var dateToCheck = new Date(2019, 11, 30)
var nextMonth = new Date()
nextMonth.setMonth(dateToCheck.getMonth() + 1)
moment(dateToCheck).isSame(nextMonth, 'month');

JavaScript to check selected date is today's date and time is 2pm using Moment.js

How do I compare today's time and date with user selected date. If user selects today's date or tomorrow's date and time is 2pm or more than 2pm then I should show alert saying delivery time over.
I have tried something like this
$scope.checkDateTime=function(){
angular.forEach($scope.orders.start_date,function(s){
console.log(s);
var curTime = moment().format('YYYY-MM-DD HH:mm:ss');
var orderTime = s+' 14:00:00';
console.log(moment(orderTime).diff(curTime,'seconds'));
if(moment(orderTime).diff(curTime,'seconds')>86400) {
console.log('hooray!')
}
})
}
I have orders.start_date is a input field inside ng-repeat so I am using forEach loop. I just want to check if selected date is today's or tomorrow's date. Then I have to check time, and if it's greater than 2pm then I should not allow. Otherwise I can allow.
I am not sure when the acceptable order period starts (since checking if the day is today or tomorrow means that everything from 00:00 to 14:00 is a fair game) , but here is the is one way to do it based on your code:
$scope.checkDateTime = function(){
angular.forEach($scope.orders.start_date, function(s){
console.log(s);
var selectedTime = moment(s);
// create boundaries for time ranges
var today_end = moment("14:00","HH:mm"); // today 14:00
var today_start = moment().subtract(1,'day').endOf('day'); // end of yesterday (since we need to include 00:00 of today)
var tomorrow_end = moment("14:00","HH:mm").add(1,'day'); // tomorrow 14:00
var tomorrow_start = moment().endOf('day'); // end of today (since we need to include 00:00 of tomorrow)
// check if time in questions fits any of the ranges
if( ( selectedTime.isBetween(today_start, today_end) ||
( selectedTime.isBetween(tomorrow_start, tomorrow_end) )
console.log('hooray!')
}
})
}
Note, that isBetween(t1, t2) does not include t1 and t2 into the accepted range.

JavaScript Smart Date Filtering

I have an array of some dates that have gaps in them. I want to be able to get the first day of each month in my dataset, given that gaps may fall on the 01 day of the month.
What is the best way to do this?
dates are in MM/DD/YYYY format.
dates = [10/31/2014, 11/03/2014, 11/04/2014, 11/05/2014, ...]
I want the result of the filter to be 11/03/2014, which is the first day of Nov 2014 that is contained in my data set. Weekends are omitted from the data set in this example.
But assuming my data set is large and continues with more gaps, I want to find the first day of every month.
function foo(list, month) {
var monthdates = list.filter(function(e,i,a) {
if(Number(e.split("/")[0]) == month)
return e;
});
var leastdateofmonth = monthdates.reduce(function(p,c,i,a) {
var pd = Number(p.split("/")[1]);
var cd = Number(c.split("/")[1]);
if(pd < cd)
return p;
else
return c;
});
console.log(leastdateofmonth);
}
//call it like this
foo(["10/31/2014", "11/03/2014", "11/04/2014", "11/05/2014"],11);
Test results:
[anupam#localhost ~]$ node sortmonth.js
11/03/2014
Call the function for each month and append it to a "leastdate" list. Here I called it for month 11.
Also consider, using a callback instead of returning, so that nothing gets blocked.

How can I make Datejs return only the year when only the year is given?

I'm using Datjs to take a date from a user and convert it to a format suitable for storage in my database. When I supply a date with month, day, and year, I get just what I want, the date formatted year-month-day:
var d1 = Date.parse('02/22/1984');
console.log(d1.toString('yyyy-MM-dd')); //Prints '1984-02-22'
However, when I give a year only, I get back the same year, followed by today's month and day:
var d1 = Date.parse('1984');
console.log(d1.toString('yyyy-MM-dd')); //Prints '1984-12-19'
What can I do to ensure that when the user types in nothing but a year that just that year is returned in the following format
1984-00-00
Likewise, if only the month and year are give I'd like it formatted like this:
1984-02-00
Datejs returns a JavaScript Date object. This object is intended to represent a point in time and a point in time necessarily includes the month and day. When not provided, Datejs defaults these values to the current month and day. If you don't want to display that information, then change your formatting pattern:
var d1 = Date.parse('1984');
console.log(d1.toString('yyyy')); // prints 1984
If you need to change the pattern based on what the user originally entered, then you need to save that information, so that you know what to print later.
A simple example follows:
function DatePrinter(input) {
var s = input.split("/").length;
this.fmt = ["dd", "MM", "yyyy"].slice(3 - s).reverse().join("-");
this.date = Date.parse(input);
}
DatePrinter.prototype.toString = function() {
return (this.date.toString(this.fmt) + "-00-00").slice(0, 10);
}
Some tests:
new DatePrinter("02/22/1984").toString() // "1984-02-22"
new DatePrinter("02/1984").toString() // "1984-02-00"
new DatePrinter("1984").toString() // "1984-00-00"

Categories

Resources