Add / Remove 1 day with Moment.js in React - reactjs

I have a div with 2 dates inside, for example (< march 25th - march 26th >), and there are 2 arrows "<" and ">"
If a user presses the "<" arrow, I need to remove 1 day to the 2 dates :
(< march 25th - march 26th >) becomes (< march 24th - march 25th >),
and if a user presses the ">" arrow, I need to add 1 day to the 2 dates :
(< march 25th - march 26th >) becomes (< march 26th - march 27th >),
I stored the 2 dates in hooks, and by default, the firstValue is the day of today and the secondValue is 1 week later
const [firstValue, setFirstValue] = useState(
moment(new Date()).format("dddd Do MMMM YYYY")
);
const [secondValue, setSecondValue] = useState(
moment(new Date())
.add(1, "weeks")
.format("dddd Do MMMM YYYY")
);
I tried this when the user presses the "<" arrow :
function previousDay() {
console.log(firstValue, secondValue);
setFirstValue(moment(firstValue).remove(1, "days"));
setSecondValue(moment(secondValue).remove(1, "days"));
}
but I have the error
TypeError: moment__WEBPACK_IMPORTED_MODULE_2___default(...)(...).remove is not a function
Can somebody know how can I do that

Based on my comments, I'd suggest the following changes:
const [firstValue, setFirstValue] = useState(
moment(new Date()) // remove .format() here
);
const [secondValue, setSecondValue] = useState(
moment(new Date())
.add(1, "weeks")
);
On your render:
render() {
<>
...
...
{firstValue.format("dddd Do MMMM YYYY")}
</>
}
And your function should be something like:
function previousDay() {
setFirstValue(firstValue.subtract(1, "days")); // don't need to moment() anymore
setSecondValue(secondValue.subtract(1, "days"));
}

Change to :
function previousDay() {
console.log(firstValue, secondValue);
setFirstValue(moment(firstValue).subtract(1, "days"));
setSecondValue(moment(secondValue).subtract(1, "days"));
}
Because "remove" is not a valid property of [Moment object].

Related

Is there a way to enable only certain calendar options?

I am trying to create a calendar which depends on a parameter. If the user wants a weekend pass I need to let him choose only one set of the days Friday, Saturday, Sunday in the period of one month.
Example:
If I choose to buy a weekend pass today 09/09/2021, I can have the options 10-12/09,17-19/09,24-26/09 for September.
The calendar has to be Infinite in order to be renewed every day. I have created the values date, month, year to get the current full date, which I parse to minDate maxDate in order to limit the options into only one month.
Code:
render() {
let newDate = new Date()
let date = newDate.getDate();
let month = newDate.getMonth();
let year = newDate.getFullYear();
let weeklyVignette = newDate.getDate();
const {label, t, value = '', loading, error, width, height, displayOptions, locale, key, required, validateOnBlur,
theme, name, proposed, disabled = false, onChange, minDateBeforeToday, setError, available=true,
minDate = new Date(year, month, date),
maxDate = new Date(year, month, date+30)} = this.props;
const {selected} = this.state;
const _locale ={...locale, ...{weekdays: locale.weekdays.map(day => t(day))}}
const resultCalendar =
this.state.open && !disabled
? <InfiniteCalendar
width={width}
height={height}
selected={value||selected||proposed}
displayOptions={displayOptions}
locale={_locale}
theme={theme}
minDate={minDate}
weeklyVignetteDays = { (weeklyVignette===4 && weeklyVignette===5 && weeklyVignette===6 )}
max = { new Date(year, month, date+30) } // Maximum month to render
min = { new Date(year, month, date) } // Minimum month to render
maxDate={maxDate}
onSelect={(e) => this.onClick(e, onChange)}
/>
: null;
How can I block all the days of the current month except Fridays, Saturdays and Sundays?
Any thoughts?
you should use the property of disabledDays
For example, to disable Monday and Sunday: [0, 6]
in your case you should use: disabledDays = [0,1,2,3]

How to filter array from one date to another in Reactjs

I have an array of objects "mainData" like so:
0: {date: "2020-07-25T16:44:43.000Z"
description: "Qwerty"
id: 89329972},
1: {date: "2020-07-25T16:46:28.000Z"
description: "Place bins please"
id: 65586316},
2: {date: "2020-07-25T16:49:12.000Z"
description: "Solve sewerege problem"
id: 84687816},
3: {date: "2020-07-27T16:34:47.000Z"
description: "Test compl"
id: 56437370},
4: {date: "2020-07-28T08:40:34.000Z"
description: "Sewerage problem in my area"
id: 92402221},
5: {date: "2020-09-09T11:42:18.000Z"
description: "problem"
id: 25613902},
Now I am allowing the user to select from and to dates by using the mui datepicker. This is how I am receiving the values:
fromDate: Sat Jul 25 2020 11:43:00
toDate: Sat Aug 08 2020 11:43:00
Now I want to filter the array from this date to that date, including the from and to dates. I tried to do it this way but it just returns an empty array. I've put the code inside useEffect which is run every time toDate changes, Also I've used Moment to make the formats of both dates same:
useEffect( () => {
if (fromDate !== null && toDate !== null) {
setReportData(
mainData.filter(
(obj) =>{
return Moment(obj.date).format("DD MMM yyyy") >= Moment(fromDate).format("DD MMM yyyy") && Moment(obj.date).format("DD MMM yyyy") <= Moment(toDate).format("DD MMM yyyy")
}
)
)
}
},[toDate])
Edit
When I select a single date :
useEffect( () => {
if (oneDate !== null) {
setReportData(
mainData.filter(
(obj) =>{
return new Date(obj.date.substring(0, 19)).getTime() === oneDate.getTime()
}
)
)
}
},[oneDate])
Your object's date property can be parsed directly to Date object. So then you can use getTime.
Also, filter returns Date object.
So, you can change your code to this
useEffect( () => {
if (fromDate !== null && toDate !== null) {
setReportData(
mainData.filter(
(obj) =>{
return new Date(obj.date).getTime() >= fromDate.getTime() && new Date(obj.date).getTime() <= toDate.getTime()
}
)
)
}
},[toDate])
If you want to consider all dates to be of local timezone, then you need to remove the last part of each date's string in order for the parse method to consider each string as local timezone date.
So previous method becomes
useEffect( () => {
if (fromDate !== null && toDate !== null) {
setReportData(
mainData.filter(
(obj) =>{
return new Date(obj.date.substring(0, 19)).getTime() >= fromDate.getTime() && new Date(obj.date.substring(0, 19)).getTime() <= toDate.getTime()
}
)
)
}
},[toDate])
We can use moment.js too. By converting the moment to expected format.
In above case we have
Sat Jul 25 2020 11:43:00
Moment provides locale support format using llll, which is similar
to this one, usage as follow.
Initialize the format constant somewhere at top, after if statement;
const format = 'llll';
And just replace the filter return statement with :
return Moment(obj.date, format).unix() >= Moment(fromDate, format).unix() && Moment(obj.date, format).unix() <= Moment(toDate, format).unix()

Datepicker shows today's date when using format ''$filter('date')($scope.dt.datetime, 'd MMM, yyyy');' what to do? using angular js datepicker

I want date-picker to show the selected date in the format 15 Jun, 2019, but instead of the selected date it highlights today's date. But it shows the actual selected date when using the format 2019-06-15 instead.
I am using angularjs date-picker from this link
<input ng-show="toggleMe" type="text" readonly placeholder="Deadline"
class="date-picker" ng-datetime-picker="datePickerOptions"
ng-model="deadlineTask" ng-change="changeCurrentTime()" />
// in ng-model wanna show deadlineTask format here what to do that i show format in 'deadlinetask type format an it highlight selected date not the today's date'
angular.module('demo', ['ngDatetimePicker'])
.controller('datePickerCtrl',function($scope,$filter) {
$scope.dt = {};
var currentTime = new Date();
var year = currentTime.getFullYear();
var month = currentTime.getMonth() + 1;
var date = currentTime.getDate();
console.log(currentTime);
$scope.dt.datetime = '2019-06-15'; //showing correct date in this format
$scope.deadlineTask = $filter('date')($scope.dt.datetime, 'd MMM, yyyy');
//showing today's date in this format this format i want but not highlighting the selected date instead of it showing today's date
You want the datepicker to always be using a date format that you define?
Based on the documentation the datepicker you have chosen does not seem to be able to show the format '15 Jun, 2019'. Maybe have a look at another AngularJs datetime picker if that is the case such as this one
To test it I see from your html that you should have an object called datePickerOptions on $scope?
If that is the case define a property called dateFormat within the datePickerOptions object and give it a string value e.g. 'MM, YYYY'
Here you can see this is how they define the date format of an input field:
Here are the formatting options listed:
YYYY: Year, 4 digit
YY: Year, 2 digit
MM: Month, 01-12
M: Month, 1-12
DD: Day, 01-31
D: Day, 1-31
HH: Hour using 12-hour clock 01-12
H: Hour using 12-hour clock 1-12
hh: Hour using 24-hour clock 00-23
h: Hour using 24-hour clock 0-23
mm: Minute, 00-59>
m: Minute, 0-59
tt: am/pm
TT: AM/PM
<input ng-show="toggleMe" type="text" readonly placeholder="Deadline" class="date-picker" ng-datetime-picker="datePickerOptions" ng-model="dt.datetime" ng-change="changeCurrentTime()" />
<script>
angular.module('demo', ['ngDatetimePicker']).
controller('datePickerCtrl', function($scope,$filter) {
$scope.dt = {};
var currentTime = new Date();
var year = currentTime.getFullYear();
var month = currentTime.getMonth() + 1;
var date = currentTime.getDate();
currentTime = year + "-" + month + "-" +"29"+ " 9:00";
$scope.dt.datetime = '2019-06-15';
$scope.deadlineTask = $filter('date')($scope.dt.datetime, 'd MMM, yyyy');
$scope.toggleMe = false;
$scope.datePickerOptions = {
"closeOnSelected": true,
"firstDayOfWeek": 1,
"dateOnly": true
};
$scope.datetimePickerOptions = {
"closeOnSelected": true,
"firstDayOfWeek": 1
};
});

React Native Create Components with multiple condition

I have a data structure like this:
const _ = require('lodash');
const bills = [
{year:2021, month:5, bill:'bill in 2021 may'},
{year:2018, month:1, bill:'bill in 2018 jan'},
{year:2019, month:1, bill:'bill in 2019 jan'},
{year:2018, month:2, bill:'bill in 2018 feb'},
{year:2019, month:10,bill:'bill in 2019 oct'},
{year:2019, month:2, bill:'bill in 2019 feb'},
{year:2019, month:6, bill:'bill in 2019 jun'},
{year:2020, month:11,bill:'bill in 2020 nov'}
];
and I want to display like below using Text or Card component of native-base
2018
1
bill in 2018 jan
2
bill in 2018 feb
2019
1
bill in 2019 jan
2
bill in 2019 feb
6
bill in 2019 jun
10
bill in 2019 oct
2020
11
bill in 2020 nov
2021
5
bill in 2021 may
My codes are below using lodash library to generate above and display in the terminal
// sort the data first
let arrSortedTasks = _.orderBy(tasks, ['year', 'month'],['asc']);
// get all the different year from the data
let arrUniqYear = _.uniqBy(arrSortedTasks, 'year');
// get all the different month from the data
let arrUniqMonth = _.uniqBy(arrSortedTasks, 'month');
// take out only the value of the year
arrUniqYear =_.map(arrUniqYear, 'year');
// take out only the value of the month
arrUniqMonth =_.map(arrUniqMonth, 'month');
let taskList = '';
for (let year of arrUniqYear) {
console.log(year);
for (let month of arrUniqMonth) {
let displayMonth = false;
for (let obj of arrSortedTasks) {
if (obj.year === year && obj.month === month) {
taskList = taskList + obj.task;
displayMonth = true;
}
}
if (displayMonth) {
console.log(" " + month);
}
if (taskList.length > 0) {
console.log(" " + taskList);
}
taskList = '';
}
}
How can we display the components in react-native with native-base? SO here don't let me post if too many code sigh. I tried a few ways buy got errors and can't figure out.
I end up using array as a return object in rendering
renderBillsSection() {
const { bills } = this.props;
if(bills || bills.length > 0 ) {
let arrSortedTasks = _.orderBy(tasks, ['year', 'month'],['asc']);
let arrUniqYear = _.uniqBy(arrSortedTasks, 'year');
let arrUniqMonth = _.uniqBy(arrSortedTasks, 'month');
let billList = '', arr = [], yearIndex = 0, monthIndex = 0, billIndex = 0;
arrUniqYear = _.map(arrUniqYear, 'year');
arrUniqMonth = _.map(arrUniqMonth, 'month');
for (let year of arrUniqYear) {
arr.push(<Text key="{yearIndex}">{year}</Text>)
yearIndex++
for (let month of arrUniqMonth) {
let displayMonth = false;
for (let obj of arrSortedTasks) {
if (obj.year === year && obj.month === month) {
billList = billList + obj.task
displayMonth = true
}
}
if (displayMonth) {
arr.push(<Text key="{monthIndex}" style={{marginLeft:10}}>{month}</Text>)
monthIndex++
}
if (billList.length > 0) {
arr.push(<Text key="{taskIndex}" style={{marginLeft:20}}>{billList}</Text>)
billIndex++
}
billList = '';
}
}
return arr;
}
}
not sure about how you are planning to render it in UI, but if you want to have the data structure like this, you need to group it (and sort by monhts if its not already sorted)
_(bills).groupBy('year').map((v,k)=> ({year: k, docs: _.sortBy(v,'month')})).value()
it will give you another array where you have year, abd docs as nested array holding all the documents of that year, so that you can agaib have another repeat on that.
const bills = [
{year:2021, month:5, bill:'bill in 2021 may'},
{year:2018, month:1, bill:'bill in 2018 jan'},
{year:2019, month:1, bill:'bill in 2019 jan'},
{year:2018, month:2, bill:'bill in 2018 feb'},
{year:2019, month:10,bill:'bill in 2019 oct'},
{year:2019, month:2, bill:'bill in 2019 feb'},
{year:2019, month:6, bill:'bill in 2019 jun'},
{year:2020, month:11,bill:'bill in 2020 nov'}
]
let groupedDoc = _(bills).groupBy('year').map((v,year)=> ({year, docs: _.sortBy(v,'month')})).value();
console.log(groupedDoc);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
Here is a working snippet:
I think you should do :
const gropuByYear = _.groupBy(bills,'year');
console.log(_.map(groupByYear, groups =>
groups.forEach(group=>(<View> {obj.bill}</View>)))
even you can orderBy year desc first then do the loop good luck
You need to take a look at SectionList of React Native.
Checkout this example and cuiyueshuai for more practical example.
SectionList Demo:
<SectionList
renderItem={({ item, index, section }) => <Text key={index}>{item}</Text>}
renderSectionHeader={({ section: { title } }) => <Text style={{ fontWeight: 'bold' }}>{title}</Text>}
sections={[
{ title: 'Title1', data: ['item1', 'item2'] },
{ title: 'Title2', data: ['item3', 'item4'] },
{ title: 'Title3', data: ['item5', 'item6'] },
]}
keyExtractor={(item, index) => item + index} />

how to enable two day only in react-day-picker

I need to enable two days only in my react-day-picker. The remaining days should be disabled. Could anyone give me an example of how to accomplish this?
I tried with this example but it not working for me.
export default function Example() {
getDaysInMonth(month, year){
// Since no month has fewer than 28 days
let date = new Date(year, month, 1);
const days = [];
while (date.getMonth() === month) {
dateys.push(new Date(date));
date.setDate(date.getDate() + 1);
}
return days;
}
const disabledMonth = this.getDaysInMonth(12, 2017);
return (
<DayPicker
initialMonth={new Date(2017, 3)}
disabledDays={
this.disabledMonth.filter(
(date) => ![new Date(2017, 12, 3), new Date(2017, 12, 13)].includes(date)
)
}
/>
);
}
i tried to run this code i getting empty array
An option is that you could set that the user should not be able to change the month if the two days are within the same month. You can set which month this is with initial month.
You can then set the disabled days which will be an array of dates which is the days of that month excluding the two available days.
Example:
If you use something like this to have a method to get all dates in a month, you could do something like this:
import React from 'react';
import DayPicker from 'react-day-picker';
import 'react-day-picker/lib/style.css';
export default function Example() {
const disabledMonth = getDaysInMonth(11, 2017);
return (
<DayPicker
initialMonth={new Date(2017, 11)}
disabledDays={
this.disabledMonth.filter(
(date) => ![new Date(2017, 11, 3).toString(), new Date(2017, 11, 13).toString()].includes(date.toString())
)
}
/>
);
}
Here i am filtering out two dates, the 3rd and 13th of december, which should be available.
This is written with es6

Resources