React - convert date with date-fns - reactjs

I have a date in this format: 12-21-2021
This date comes from a Redux selector.
So console.log('ccc', lastUpdateDate); at the beginning shows only:
ccc
and after few times shows
ccc 12-21-202
If I use new Date(lastUpdateDate).toDateString() it turns out it works only in Chrome, whereas FireFox and Safari say this is an invalid date.
So I want to convert it in the right way using a function.
So I created this function:
const parseDateWithDashes = (dateToParse) => {
console.log('dateToParse', dateToParse);
useEffect((): any => {
let finalDate;
dateToParse instanceof Date && dateToParse.getTime()
? (finalDate = format(dateToParse, "yyyy-MM-dd'T'HH:mm:ss.SSSxxx"))
: null;
console.log('finalDate', finalDate);
return finalDate;
}, [dateToParse]); //since at the beginning it is empty, it should re-run as a date is available
};
parseDateWithDashes(lastUpdateDate)
However doing this it logs out:
dateToParse (several time empty)
dateToParse 12-21-2021
finalDate undefined (several times)
I've also tried to run the function in a useEffect...
useEffect(() => {
parseDateWithDashes(lastUpdateDate);
});
But that's an invalid hook call.
What am I doing wrong? How to fix that?

I resolved it this way.
I added the parsing to the thunk. And stringified in order to avoid non-serialized errors:
const parsedDate = parse(lastUpdateDate, 'MM-dd-yyyy', new Date());
dispatch(setLastUpdateDate(JSON.stringify(parsedDate)));
Then I just formatted it in the component:
export const convertStringDateToDate = (date: string) => {
let finalDate;
try {
finalDate = JSON.parse(date);
finalDate = format(parseISO(finalDate), 'E LLL d yyyy');
} catch (e) {
finalDate = 'loading date';
}
return finalDate;
};
That works

Related

Firebase's onValue only get data once and does not update when placed inside a loop in React's useEffect

My goal is to get multiple data based on a list of data the customer requested so I put the codes inside useEffect. If the array contains the list of things the customer wants, then it grab those data from the server so the user can manipulate it. So far, it works fine but when the database updates, onValue is not triggered to grab the new data to update the render.
Here is my code. Thank you for helping me in advance.
// Getting data
useEffect(() => {
if (empDataArr.length > 1) {
let fromDay = parseInt(dateHandler(startDate).dateStamp);
let toDay = parseInt(dateHandler(endDate).dateStamp);
let tempLogArr = [];
empDataArr.forEach((emp) => {
let qLogEvent = query(child(shopRef(shopId), emp.id + "/log_events"), orderByChild("dateStamp"), startAt(fromDay), endAt(toDay));
// This is the part I need help
onValue(qLogEvent, (snap) => {
let logEventArr = [];
let val = snap.val();
if (val === null) {
} else {
Object.keys(val).forEach((key) => {
let id = key;
let dateStamp = val[key].dateStamp;
let direction = val[key].direction;
let time = val[key].timeStamp + "";
let timeStamp = time.substring(8, 10) + ":" + time.substring(10, 12);
logEventArr.push({ direction: direction, timeStamp: timeStamp, dateStamp: dateStamp, id: id });
});
tempLogArr.push({
id: emp.id,
logEvent: logEventArr,
});
}
});
});
setLogDataArr(tempLogArr.map((x) => x));
}
}, [empDataArr, shopId, startDate, endDate]);
useEffect(() => {
console.log(logDataArr);
}, [logDataArr]);
I have tried using return onValue() and const logData = onValue() but they do not work (and I do not expect the former one to work either).

Creating a reusable date formatter in React

I've been struggling to create a reusable function that I can call on dates in my data. The goal is to take any date given, determine if it has just a date, or date and time, then return the data in the appropriate format.
I've been using moment to format things, but am not sure how to actually call this function on the data. I'm very new to React
Here is what I've got so far:
import moment from "moment";
const FormatDate = (dateObject) => {
var dateMutant = dateObject;
var dateMutated = "";
function justDate() {
//formats just a date
dateMutated = moment.utc(dateMutant).format("MM-DD-YYYY");
}
function dateTime() {
//formats a date and time
dateMutated = moment.utc(dateMutant).format("MM-DD-YYYY hh:mm:a");
}
console.log(dateMutated);
return dateMutated;
};
export default FormatDate
I am attempting to call it in a page like this:
React.useEffect(() => {
var testDate = '';
if (allCommentsFetch) {
setAllCommentsLoading(true);
axios
.get(`###API Hook##`)
.then(response => {
let comments = response.data;
comments.forEach(commentfield => {
if (commentfield != null) {
commentfield['commentTimestamp'] = moment.utc(commentfield.commentTimestamp).format('YYYY-MM-DD hh:mm:ss');
testDate = FormatDate(commentfield.commentTimestamp).justDate();
} else {
comments[commentfield] = 'N/A'
}
})
but am getting an error that Object(...)(...).justDate is not a function.
you can write it in a better and cleaner way, first of all, you have not to write your module names in PascalCase, getFormattedName will be a better choice! the second thing is that you are using var... avoid that.
the only thing you have to change in the format function is a format template... and as i see you have only two option (justDate and dateTime) in this case, so let's write it again:
const getFormattedDate = ({ dateObject, includeTime }) => {
const dateFormat = includeTime ? 'MM-DD-YYYY hh:mm:a' : 'MM-DD-YYYY';
return moment.utc(dateObject).format(dateFormat);
};
and about the error you got: (but am getting an error that Object(...)(...).justDate is not a function) the problem is that you didn't return justDate from the FormatDate function.

ReactJs: Group data by today, current week, current year

I have data in the following format
[
0:{
address:n/a
booking_status:null
commission_total:"65000.00"
created_at;"Tue, Jun, 2020"
},
1:{
address:n/a
booking_status:null
commission_total:"68000.00"
created_at;"Thur, Jun, 2020"
}
]
I am looking to group the set of data as described the subject line in ReactJs. Will anyone assist please
The easiest way is to use some sort of library for handling dates, like date-fns which have some builtin functions like isSameWeek and isSameYear
https://date-fns.org/v2.0.0-alpha.2/docs/isSameYear
Then it will be easy as filtering the array and extracting the ones that match
const today = new Date();
const todayGroup = data.filter(item => isSameDay(new Date(item.created_at), today));
const weekGroup = data.filter(item => isSameWeek(new Date(item.created_at), today));
const yearGroup = data.filter(item => isSameYear(new Date(item.created_at), today));
You can use Moment
var REFERENCE = moment("2015-06-05"); // fixed just for testing, use moment();
var TODAY = REFERENCE.clone().startOf('day');
var YESTERDAY = REFERENCE.clone().subtract(1, 'days').startOf('day');
var A_WEEK_OLD = REFERENCE.clone().subtract(7, 'days').startOf('day');
function isToday(momentDate) {
return momentDate.isSame(TODAY, 'd');
}
function isYesterday(momentDate) {
return momentDate.isSame(YESTERDAY, 'd');
}
function isWithinAWeek(momentDate) {
return momentDate.isAfter(A_WEEK_OLD);
}
function isTwoWeeksOrMore(momentDate) {
return !isWithinAWeek(momentDate);
}
console.log("is it today? ..................Should be true: "+isToday(moment("2015-06-05")));
console.log("is it yesterday? ..............Should be true: "+isYesterday(moment("2015-06-04")));
console.log("is it within a week? ..........Should be true: "+isWithinAWeek(moment("2015-06-03")));
console.log("is it within a week? ..........Should be false: "+isWithinAWeek(moment("2015-05-29")));
console.log("is it two weeks older or more? Should be false: "+isTwoWeeksOrMore(moment("2015-05-30")));
console.log("is it two weeks older or more? Should be true: "+isTwoWeeksOrMore(moment("2015-05-29")));

Moment.js is converting Date to Today date using React Big Calendar

I've got a problem where the date is being converted to today's date even though the date is being parse by moment. It looks like Moment is converting the date to today's date. I believe I am just using the script incorrectly. I'm not familiar with Moment. Any help would be appreciated.
export function getEvents (callback) {
request
.get(url)
.end((err, resp) => {
if (!err) {
const events = [];
JSON.parse(resp.text).items.map((event) => {
events.push({
start: moment(event.start.date).toDate()|| moment(event.start.dateTime),
end: moment(event.end.date).toDate() || moment(event.end.dateTime),
title: event.summary,
})
});
callback(events)
}
})
This is an example of the trace where the "start" date from Google Calendar is in a Timeformat.
This is the conversion and a trace of the script
Here is the date in real time on the call:
The issue that fixed this is in the Moment api. Use this :
JSON.parse(resp.text).items.map((event) => {
var start = moment(event.start.dateTime,'YYYY-MM-DD HH:mm').toDate();
var end = moment(event.start.dateTime,'YYYY-MM-DD HH:mm').toDate();
events.push({
start: start,
end: end,
title: event.summary,
})
});
After looking into your resp.text that provided in comments I created the following parse method to parse your response as the way you wanted.
Here response passed to this method is your resp.text which you supplied in comments.
import moment from 'moment'
const parseResponse = (response) => {
const events = []
response.forEach(obj => {
obj.items.forEach(
item => {
events.push({
start: moment(item.start.dateTime),
end: moment(item.end.dateTime),
title: item.summary
})
}
)
})
return events
}
Note: Check the codesandbox.io/s/ywpznzrmv9 pen if you want to look into moment workaround. You can get rid of first forEach block if the resp.text is having only one array of object.|
like:
const parseResponse = (response) => {
const events = []
response[0].items.forEach(
item => {
events.push({
start: moment(item.start.dateTime),
end: moment(item.end.dateTime),
title: item.summary
})
}
)
return events
}
Note: If you stick to using JSON.parse() then change map to forEach. map creates an object, which is a garbage that you won't need in your case.

setState not working in React JS

I am trying to give few dates to state.periods array. But it is not working. My code is as follows.
class SmallTable extends Component {
constructor(props) {
super(props);
console.log(props.startDate)
this.state = {
turns: [],
periods: []
}
}
componentDidMount() {
//calculate years/ months and keep in one array
const today = new Date();
var periods1 = [];
if (this.props.period=="year") { //if year calculate from last year last date
const lastYearLastDate= new Date(new Date().getFullYear()-1, 11, 31)
periods1.push(lastYearLastDate.getFullYear()+"-"+(lastYearLastDate.getMonth()+1)+"-"+lastYearLastDate.getDate());
var lastYearFirstDate= new Date(lastYearLastDate.getFullYear()-1,0,1);
//for the remaining periods
for (var i=0;i<this.props.numberOfPeriods-1;i++) {
periods1.push(lastYearFirstDate.getFullYear()+"-"+(lastYearFirstDate.getMonth()+1)+"-"+lastYearFirstDate.getDate());
lastYearFirstDate = new Date(lastYearFirstDate.getFullYear()-1,0,1);
}
}
else if (this.props.period=="month") {//if month calculate from last month last date
var d=new Date(); // current date
d.setDate(1); // going to 1st of the month
d.setHours(-1); // going to last hour before this date even started.
var lastMonthLastDate = d;
periods1.push(lastMonthLastDate.getFullYear()+"-"+(lastMonthLastDate.getMonth()+1)+"-"+lastMonthLastDate.getDate());
//go to last month first date
var lastMonthFirstDate = new Date(lastMonthLastDate.getFullYear(), lastMonthLastDate.getMonth(),1);
//for the remaining periods
for (var i=0;i<this.props.numberOfPeriods-1;i++) {
periods1.push(lastMonthFirstDate.getFullYear()+"-"+(lastMonthFirstDate.getMonth()+1)+"-"+lastMonthFirstDate.getDate());
lastMonthFirstDate=new Date(lastMonthFirstDate.getFullYear(), lastMonthFirstDate.getMonth()-1,1);
}
}
console.log(periods1); -->prints ["2017-12-31", "2016-1-1", "2015-1-1", "2014-1-1"]
this.setState((prevState)=>{
return {
periods: prevState.periods.push(periods1)
}
});
console.log(this.state.periods) --> prints []
}
render() {
return ( <div></div>)
}
How to get values in periods1 to periods state. I am trying to insert periods1 array into state periods array. Those are strings. Pls suggest where the error might be.
You're setting this.state.periods to the result of a push operation. But push returns the new array length, not the array itself. Try this instead:
periods: [...prevState.periods, periods1]
push() doesn't return a value.
You should use:
this.setState((prevState)=>{
let old = prevState.periods.slice();
old.push(periods1);
return {
periods: old
}
});
You have a few issues.
For the code here:
return {
periods: prevState.periods.push(periods1)
}
You never want to mutate state. Instead, you should create a new array object and then add the data, like so:
return {
periods: prevState.periods.concat([periods1])
}
Secondly, your console.log is in the wrong place
console.log(this.state.periods) --> prints []
setState happens asynchronously and thus may not finish by the time your componentDidMount method returns. Instead, put that console.log inside your render function to see the new state.
If you expect this.state.periods to be an array of arrays ([["2017-12-31", "2016-1-1", "2015-1-1", "2014-1-1"]]) you can push your array following an immutable pattern using the spread operator :
this.setState((prevState) => ({
periods: [...prevState.periods, periods1]
}), () => { console.log(this.state.periods) } );
You can notice the function passed as second param of setState() is a callback to execute console.log() after the state update.
If you want to push periods1 values in this.state.periods you can do this :
this.setState((prevState) => ({
periods: [...prevState.periods, ...periods1]
}));
Try to make a copy of your original state, so that you can perform setState in an immutable fashion.
const periods = [...this.state.periods];
periods.push(periods1);
this.setState({periods: periods});

Resources