How to set date range selection in react JS DateRangePicker? - reactjs

I am using 'DateRangePicker' component in my react JS application.
I am trying to restrict start date to last 6 month only and difference between
start and end date should not be more than 1 month.
I wrote following code
isOutsideRange = (day) => {
if (day > moment()) return true;
else if (this.state.startDate) {
if (day > moment(this.state.endDate)) return true;
if (day < moment().subtract(6, 'months')) return true;
else return false;
} else if (this.state.endDate) {
if (day > moment(this.state.endDate)) return true;
if ((moment(this.state.endDate) > (moment(this.state.startDate).subtract(1, 'month')))) return true;
else return false;
}
}
and here is the UI code
<DateRangePicker
startDate={this.state.startDate}
startDateId="validFromDate"
endDate={this.state.endDate}
endDateId="validToDate"
onDatesChange={({ startDate, endDate }) =>
this.handleValidDatesChange(startDate, endDate)
}
focusedInput={this.state.ofrFocusedInput}
onFocusChange={(ofrFocusedInput) => this.setState({ ofrFocusedInput })}
isOutsideRange={(e) => this.isOutsideRange(e)}
showDefaultInputIcon={true}
small={true}
minimumNights={0}
hideKeyboardShortcutsPanel={true}
showClearDates={true}
min={this.maxDate}
shouldDisableDate={({ startDate }) => this.disablePrevDates(startDate)}
// minDate={subDays(new Date(), 10)}
displayFormat={() => "DD/MM/YYYY"}
/>;
I tried to debug but it is not working.
Can someone suggest the solution ?

To check if a moment is between two other moments, optionally looking at unit scale (minutes, hours, days, etc), you should use:
moment().isBetween(moment-like, moment-like, String, String);
// where moment-like is Moment|String|Number|Date|Array
For instance, if you need to check today - 6months <= someDate <= today, you would use something like:
// returns TRUE if date is outside the range
const isOutsideRange = date => {
const now = moment();
return !moment(date)
.isBetween(now.subtract(6, 'months'), now, undefined, '[]');
// [] - match is inclusive
}
For more details, please check Is Between docs. This method is very flexible, for instance, you can have exclusive or inclusive match.
Now, the second condition. If you would like to check if endDate - startDate <= 1 month, you can play with moments as well to achieve this.
// so if you add 1 month to your startDate and then your end date
// is still before the result or the same - you can say the duration
// between them is 1 month
const lessThanMonth = (startDate, endDate) => {
return endDate.isSameOrBefore(moment(startDate).add(1, 'months'));
}

if (day.isAfter(moment()) ||
!day.isAfter(moment().subtract(6,'months'))) return true;

Related

How to dynamically disable days in react datepicker

I am using React DatePicker .I want to disable days in date picker. I am able to doing so by passing day number like below so Monday Tuesday and Saturday get's disabled.But how do I achieve this dynamically? I am able to form array like this
var notAvailableDays=[1,2,6] // which should disable these days. How do I return this at once?
const isWeekday = (date) => {
const day = date.getDay(date);
return day !== 1 && day !== 2 && day !== 6;
}
;
You can do an array lookup like this
const notAvailableDays = [1,2,6];
const isDisabled = (date) => {
const day = date.getDay(date);
return notAvailableDays.includes(day);
}

Display current date calendar react?

I am building a calendar, it has 53 weeks from (12-30-2019 -> 03-01-2021). How when the app first loads it display current date.
// the function display dates
export default function RenderDates(props) {
const dates_ = [];
const startDate = moment('12-29-2019', 'MM-DD-YYYY');
// display date in week
for(let i = 1; i <= 53*7; i++) {
dates_.push(
<Date>
<ContentDate>
<ShortDate>{moment.weekdaysShort()[i%7]}</ShortDate>
<span>{startDate.add(1,'days').get('Date')}</span>
</ContentDate>
</Date>
)
}
return dates_;
}
demo: https://codesandbox.io/s/github/Kalipts/scroll_calendar?file=/src/components/RenderDates.js
You can assign unique id to every date box and then focus today's box
https://codesandbox.io/s/quirky-leavitt-w2x3w
export default function RenderDates(props) {
const dates_ = [];
const startDate = moment("12-29-2019", "MM-DD-YYYY");
useEffect(() => {
const today = moment().format("YYYY-MM-DD");
console.log('today', today);
const node = document.getElementById(today);
if (node) {
node.setAttribute("tabindex", "-1");
node.focus();
node.removeAttribute("tabindex");
}
}, []);
for (let i = 1; i <= 53 * 7; i++) {
const date = startDate.add(1, "days");
dates_.push(
<Date id={date.format("YYYY-MM-DD")}>
<ContentDate>
<ShortDate>{moment.weekdaysShort()[i % 7]}</ShortDate>
<span>{date.get("Date")}</span>
</ContentDate>
</Date>
);
}
return dates_;
}
I just changed a bit your codesandbox to make it work and here is the link: https://codesandbox.io/s/vibrant-worker-b2xhq?file=/src/App.js
Basically what I did was:
On your RenderDates component I check for the current date and added an id to the Date component if that date was the current one.
On App component (It could be on RenderDates component) I added a useEffect to run once the component is mounted that getElementById using the id on date and scrollIntoView.
It is very simple and works well! :)

Comparing 2 dates to see if the current date is passed - React/Momentjs

I'm currently tying to compare 2 dates (and time): the date limit my action has to be completed and the current date.
I receive the date and time in this format: 2017-05-29T15:30:17.983Z.
I then try to compare the 2 dates using this function:
function checkExceedLimit (props) {
exceedLimit = 0;
props.items.map((item) => {
var dateLimit = moment(item.limit)
var now = moment()
if (item.limit != null || item != ' ' && now > dateLimit) {
exceedLimit++;
console.log(now)
console.log(dateLimit)
}
})
}
Basically I want to compare the limit from each item and add +1 to exceedLimit when the current date is passed. Yet it returns +1 for each limit even though not all of them are passed.
Thank you for your help
Simply use isBefore and isAfter, in your case you can do:
if (item.limit != null || item != ' ' && now.isAfter(dateLimit) ) {
First of all you should proper create your instance of moment.
Like this:
moment("2017-05-29T15:30:17.983Z", 'YYYY-MM-DDTHH:mm:ss.SSSZ')
You can check this link for more details: https://momentjs.com/docs/#/parsing/string-format/
And then you can compare date using the moment's API methods on https://momentjs.com/docs/#/query/
So your code should look like this:
function checkExceedLimit (props) {
exceedLimit = 0;
props.items.map((item) => {
const dateLimit = moment(item.limit, 'YYYY-MM-DDTHH:mm:ss.SSSZ');
const now = moment()
if (dateLimit.isValid() && now.isAfter(dateLimit)) {
exceedLimit++;
console.log(now.toString())
console.log(dateLimit.toString())
}
})
}

How to parse /Date(-62135596800000)/ to null

I get from the server dates, sometimes null, and my filter parse /Date(-62135596800000)/ to 0001-01-01 but I would like to have empty string.
How can I do this?
Here's my filter:
filter('myDateFormat', function() {
return function (data) {
return moment(data).format("YYYY-MM-DD");
};
})
Well your server is returning you null or a date string.
null can be handled by simple null check but for your other input "Date(-62135596800000)" which is a valid date, you can't return empty string, without explicitly checking for it.
moment(Date(-62135596800000)).isValid() // return 'true'
you may try below code.
// if inputDate not defined or null
if (!inputDate || inputDate == null) {
return '';
} else if (moment(inputDate).isValid()){
return moment(inputDate).format("DD MM YYYY");
} else {
return '';
}
but if your server is returning this specific date occasionally 'Date(-62135596800000)' and you want to avoid this, you can put explicit check for it.
if (!inputDate || inputDate == null) {
return '';
}
if (inputDate == 'Date(-62135596800000)') {
return '';
} else if (moment(inputDate).isValid()) {
return moment(inputDate).format("DD MM YYYY");
} else {
return '';
}
The filter could be improved like this:
filter('myDateFormat', function() {
return function (data) {
return data > 0 ? moment(data).format("YYYY-MM-DD") : "";
};
})
First of all decide what should be your minimum date.
For example SQL's minimum date is 1753-01-01
After that compare your date with this minimum date like:
filter('myDateFormat', function() {
return function (data) {
var minDate = moment('1753-01-01');// decide your minimum date
return moment(data).diff(minDate) > 0 ? moment(data).format("YYYY-MM-DD") : "";
};
})

ExtJS Parsing Date Incorrectly

When I enter "31/12/2012" in my field (date format is MM/DD/YYYY), it changes the date to "7/12/2014" in the field. I would rather it error with a "not valid" error message.
I have inherited this code from a previous developer:
function dateRangeCheck(val, field) {
field.vtypeText = '';
var date = field.parseDate(val);
if (!date) {
field.vtypeText = val + ' is not a valid date - it must be in the format (MM/DD/YYYY).';
return false;
}
var retVal = true;
if (field.fromField) {
var fromField = Ext.getCmp(field.fromField);
var fromDate = fromField.parseDate(fromField.getValue());
// If we don't have a fromDate to validate with then return true
if (!fromDate)
return true;
retVal = (date >= fromDate);
if (retVal)
fromField.clearInvalid();
}
else if (field.toField) {
var toField = Ext.getCmp(field.toField);
var toDate = toField.parseDate(toField.getValue());
// If we don't have a toDate to validate with then return true
if (!toDate)
return true;
retVal = (date <= toDate);
if (retVal)
toField.clearInvalid();
}
if (!retVal) {
field.vtypeText = 'From Date must be less than or equal to To Date.';
}
return retVal;
}
When I try to use the default 'daterange' vtype, as soon as I type a "3" in the field, it throws a JS runtime exception 'object doesn't support this property or method'.
Note that you can set Date.useStrict = true globally and the DateField will use that by default.
For Ext 4+ it would be Ext.Date.useStrict = true instead.
It looks like your call to parseDate just needs to have the strict switch set.
strict (optional) True to validate date strings while parsing (i.e.
prevents javascript Date "rollover")(defaults to false). Invalid date
strings will return null when parsed.
> Date.parseDate('31/12/2012','m/d/Y')
Sat Jul 12 2014 00:00:00 GMT-0500 (Central Daylight Time)
> Date.parseDate('31/12/2012','m/d/Y', true)
null
The parseDate method in DateField is private and undocumented, and the discussion to allow strict date parsing in ExtJS 3.x never bore any fruit. I think your best bet is to use an override to allow strict date parsing.
// before you use your DateFields
Ext.override(Ext.form.DateField, {
safeParse : function(value, format) {
if (Date.formatContainsHourInfo(format)) {
// if parse format contains hour information, no DST adjustment is necessary
return Date.parseDate(value, format, this.strict);
} else {
// set time to 12 noon, then clear the time
var parsedDate = Date.parseDate(value + ' ' + this.initTime, format + ' ' + this.initTimeFormat, this.strict);
if (parsedDate) {
return parsedDate.clearTime();
}
}
}
});
//... and in your DateField config:
strict: true,

Resources