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

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.

Related

React multiple console.log?

Im creating a function that sends an email based on the expiry date, however, upon trial, the function works fine but the email gets sent multiple times and the console.log is shown multiple times. Does anyone know how to counteract?
if (product?.expiry) {
var arr = []
var today = new Date()
var expiry = new Date(product?.expiry)
var week = new Date(expiry.setDate(expiry.getDate() - 7))
var template = {
message: product.name + " is reaching expiry date",
footer: "Expiry Date: " + week.toDateString()
}
const interval = setInterval(() => {
if (arr.length > 0) {
clearInterval(interval)
console.log(arr)
}
if (today !== expiry) {
// actual emailing
emailjs.send(SERVICE_API, TEMPLATE_API, template, PUBLIC_API)
.then(function(response) {
console.log('SUCCESS!', response.status, response.text);
}, function(error) {
console.log('FAILED...', error)
});
arr.push('found')
}
}, 1000)
}
ALERT: I am aware that the function is sending the email when it is not the expiry date, i just want to fix up this console.log error
**rest of function: **
const expiryEmail = () => {
if (today !== week) {
emailjs.send(SERVICE_API, TEMPLATE_API, template, PUBLIC_API)
.then(function(response) {
console.log('SUCCESS!', response.status, response.text);
}, function(error) {
console.log('FAILED...', error)
});
}
}
setTimeout(() => {
})
useEffect(() => {
if (!product) {
return;
}
//problem is that the condition returns null first time around
expiryEmail()
},[])
Try to use useEffect hook instead to set interval I am sharing the code try to use that
var today = new Date()
var expiry = new Date(product?.expiry)
var week = new Date(expiry.setDate(expiry.getDate() - 7))
var template = {
message: product.name + " is reaching expiry date",
footer: "Expiry Date: " + week.toDateString()
}
useEffect(()=>{
if (today !== expiry) {
emailjs.send(SERVICE_API, TEMPLATE_API, template, PUBLIC_API)
.then(function(response) {
console.log('SUCCESS!', response.status, response.text);
}, function(error) {
console.log('FAILED...', error)
});
arr.push('found')
}
},[])
The first condition inside your setInterval method's callback, ie.
if (arr.length > 0) {
clearInterval(interval)
console.log(arr)
}
does not have a return statement, which means it will continue on to your next if block, whose condition is satisfied because you are checking is today's date is not the same as expiry 's date, which as you alerted is a conscious decision, and therefore print the console message again.
Also, I hope by multiple you mean only twice, because that is what my answer applies for, if you meant more than that, I'd like to see the part that calls this method.
Again also, you should use Mayank's suggestion and process your code inside a useEffect block, much simpler.

React - convert date with date-fns

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

Receive object datatype from back4app in react

I have an issue with receiving the datatype object from the database in back4app in the column "expiration" 1. I have no issue with receiving the other datatypes (String, Array..), but I can't deconstruct the object into day, month and year.
I have the following code where I receive the other datatypes and save it in an useState:
const [ideaTable, setIdeaTable] = useState();
async function fetchIdeas() {
const query = new Parse.Query("Idea");
try {
const ideas = await query.find();
console.log("Parse Objects: ", ideas);
const destructuredIdeas = destructureIdeas(ideas);
setIdeaTable(destructuredIdeas);
console.log("from readIdeas: ", ideaTable);
return true;
} catch (error) {
alert(`Error ${error.message}`);
return false;
}
}
function destructure(idea) {
return {
id: idea.id,
title: idea.get("title"),
section: idea.get("tags"),
author: idea.get("author"),
/* expiration: JSON.stringify(idea.get("expiration")) */
expiration: idea.get("expiration")
};
}
function destructureIdeas(ideas) {
return ideas.map(destructure);
}
Here I just call: "expiration: idea.get("expiration")" as in above code. So, I think I need to restructure the expiration object to get the day, month and year... but how?
If I do this: "expiration: JSON.stringify(idea.get("expiration"))", I get the following result 3.
So, what to do if I want to display for example: "14.12.2021"?
I found the answer myself:
expiration: idea.get("expiration").day
expiration: idea.get("expiration").month
expiration: idea.get("expiration").month

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.

Running a forEach() on an Array of Objects After Retrieving with findOne() in Mongo Back-end

I am using findOne() to retrieve a document like this:
let staffToUpdate = await Staff.findOne({
_id: request.parameters.id
}).exec();
let historyArray = await crewToUpdate.history;
console.log("historyArray: ", await historyArray);
console.log(Array.isArray(historyArray)); // returns true
The data looks like this:
history: [
{
status: "active",
startDate: <Date>,
endDate: <Date>,
completed: false
},
{
status: "training",
startDate: <Date>,
endDate: <Date>,
completed: true
}
]
When I do the above I get an array of objects printed out, as well as a return of "true" on the check to see if "historyArray" is indeed an array.
So now that I have this array, I'd like to run a transformation on the objects found within it, like so:
let updatedHistoryArray = historyArray.then(
updatedHistoryArray.forEach(history => {
history.completed = true;
history.endDate = new Date();
})
);
However, this is the part that's not working. When I try this I get this error:
Reason: ReferenceError: historyArray is not defined
What am I missing here?
UPDATE: After a suggestion from a commenter below, I tried this:
let staffToUpdate = await Staff.findOne({
_id: request.parameters.id
}).exec();
let staffObject = staffToUpdate.toObject();
let historyArray = await staffObject.history;
console.log(await historyArray); // prints the array
console.log(Array.isArray(historyArray)); // returns true
historyArray.forEach(history => { // this is where the error occurs
history.completed = true;
history.endDate = new Date();
});
With this last block of code I get this error:
Reason: ReferenceError: historyArray is not defined
historyArray is not a Promise and you can not run then on it.
When this code runs
let staffToUpdate = await Staff.findOne({
_id: request.parameters.id
}).exec();
it waits until query is executed and assigns the actual result (mongoose Document), not a promise and assigns it to staffToUpdate. You need to run toObject() on mongoose Document to get plain object without the wrapper:
const unwrappedStaffToUpdate = staffToUpdate.toObject();
After that you don't need to use await on crewToUpdate.history because it is not a Promise and it is synchronious. That is why you can not run then on historyArray because it is a normal Array and not a Promise.
Try this code:
unwrappedStaffToUpdate.historyArray.forEach(history => {
history.completed = true;
history.endDate = new Date();
});
Or if you do not want to mutate your Array use map instead of forEach:
const updatedHistoryArray = unwrappedStaffToUpdate.historyArray.map(history => ({
...history
completed: true;
endDate: new Date()
})
);

Resources