How to map/filter data correctly with luxon (DateTimeNow) and ReactJs - reactjs

I would like to explain my problem of the day.
I have a array which looks like this
[{status: "closed",createdAt: "2022-01-13T15:28:25.239Z"},{status: "closed",createdAt: "2022-01-10T15:28:25.239Z"},{status: "open",createdAt: "2021-11-25T15:28:25.239Z"}]
I filter to retrieve only the data with the status "closed"
const countData = data?.filter(
(item) => item.status === "closed"
);
const count = countData?.length;
this works well, it correctly returns the number to me.
I would like to add a new filter with Luxon.
I would like to take the date of today with luxon, and, as a result, display the objects that correspond to this date
const dateNow = DateTime.now().toISO();
console.log(dateNow)
2022-01-13T16:23:44.873+01:00
How can I fix this issue?

If you want to check if a given Luxon DateTime object represent the same day of today, you can use hasSame passing date as second parameter
Return whether this DateTime is in the same unit of time as another DateTime. Higher-order units must also be identical for this function to return true. Note that time zones are ignored in this comparison, which compares the local calendar time. Use DateTime#setZone to convert one of the dates if needed.
In your case, you can have something like the following code:
const DateTime = luxon.DateTime;
const input = [{
status: "closed",
createdAt: "2022-01-13T15:28:25.239Z"
}, {
status: "closed",
createdAt: "2022-01-10T15:28:25.239Z"
}, {
status: "open",
createdAt: "2021-11-25T15:28:25.239Z"
}, {
status: "closed",
createdAt: new Date().toISOString()
}];
const todayItems = input.filter(item => {
return DateTime.fromISO(item.createdAt).hasSame(DateTime.now(), 'day') && item.status == "closed";
});
console.log(todayItems)
<script src="https://cdn.jsdelivr.net/npm/luxon#2.3.0/build/global/luxon.js"></script>

Luxon has a function that let's you get a date at certain point of a parameter that's called startOf. So you can do something like:
const todayDate = DateTime.now().startOf("day");
So your todayDate variable will be your current date, but at 00:00:00 time.
And you can make the transformation of the elements date during your filter function to compare them to todayDate like this:
//Please consider that the example for today was at 2022-01-13
const array = [
{
name: "this is for today",
date: "2022-01-13T15:28:25.239Z"
},
{
name: "this was for yesterday",
date: "2022-01-12T15:28:25.239Z"
}];
const todayDate = DateTime.now().startOf("day");
const todayElements = array.filter((element) => {
return DateTime.fromISO(element.date).startOf("day").equals(todayDate);
});

Related

Swift - How do I add a new object to an array inside another object that has a grouping field

I have an array of events of type.
struct Event { var id: UUID, var title: String, var date: Date }
this array is inside another object with an occurrence title
struct Category { var occurs: String, var events: [Event] }
occurs defines if the event.date is before or after Now(), so that i can make Section Headers in a table to show Past and Upcoming sections.
I am only persisting Event(need id for Notification changes).
I am able to save and load data into an array of Category but how do I add a new event and get it into the correct "occurs" array.
Data Example (Event struc has init that assigns the UUID to id. )
[
Category(occurs: "passed", events: [
Event(title: "Yesterday", date: Calendar.current.date(byAdding: .day, value: -1, to: Date())!)
]),
Category(occurs: "upcoming", events: [
Event(title: "Tomorrow", date: Calendar.current.date(byAdding: .day, value: 1, to: Date())!),
Event(title: "Future", date: Calendar.current.date(byAdding: .day, value: 5, to: Date())!)
])
]
Category array is then consumed by a List/ForEach to spit out the Section and Body.
Thanks
First you need a way to figure out if the event has passed or is upcoming. You could add an extension to your Event struct to compute this:
extension Event {
var occurs: String {
let diff = date.timeIntervalSince1970 - Date().timeIntervalSince1970
return diff >= 0 ? "upcoming" : "passed"
}
}
Next you need to find the index of the category that matches the event's occurs value in your data array. You can do this by using the firstIndex method:
let newEvent = Event(
title: "2 hours from now",
date: Calendar.current.date(byAdding: .hour, value: 2, to: Date())!)
let newEventOccurs = newEvent.occurs
if let index = data.firstIndex(where: { $0.occurs == newEventOccurs }) {
data[index].events.append(newEvent)
}
Notice we use an if-let binding because it's possible you don't have a category in your array for the event. In this case, you will want to add the category to your array with the new event.

I'm trying to sort an array and then map it to a new array, but the sorting doesn't work (the map works)

I'm having trouble sorting an array and then mapping it (as part of a to do list, I'm trying to sort the tasks in the global state before mapping it to a new array.
My sandbox is here:
https://codesandbox.io/s/to-do-list-lloydr-416wm?file=/src/App.js
The place where I'm trying to do the sorting is here (I'm taking the global state of tasks as a prop and then sorting and mapping it to a new array - but only the mapping works, not the sorting):
const Tasks = ({ tasks, onDelete, onToggle }) => {
return (
<>
{tasks
.sort((a, b) =>
new Date(a.selectedDate).getTime() >
new Date(b.selectedDate).getTime()
? 1
: -1
)
.map((task) => (
<Task
key={task.id}
task={task}
onDelete={onDelete}
onToggle={onToggle}
/>
))}
</>
);
};
export default Tasks;
The initial array of tasks is here:
const [tasks, setTasks] = useState([
{
id: 1,
text: "Doctor's appointment",
selectedDate: "05/12/2021",
// CHANGED DATE TO SELECTEDDATE
priority: true
},
{
id: 2,
text: "Meet Lauren for Birthday Dinner",
selectedDate: "27/09/2021",
priority: true
},
{
id: 3,
text: "Take Nugie to vet cos she's stupid",
selectedDate: "28/09/2021",
priority: true
}
]);
Any help is appreciated, thank you!
The date format it expects is MM/dd/yyyy instead of dd/MM/yyyy.
Switch your month and day, or initialize it as a date instead of a string with new Date(2021, 29, 27) (for example).
Edit: I would recommend you to initialize dates with numbers instead of a string. This way you avoid thinking about which locale your string date should be introduced with

Updating array of objects with timestamps

I have a data structure like this :
var records = [
{
firstName: "Akira",
id: "0543236543",
},
{
firstName: "Harry",
id: "0994372684",
},
{
firstName: "Sherlock",
id: "0487345643",
},
{
firstName: "Kristian",
id: "04873452342",
},
];
I want to create a function that would add the date property (adjusted for hours) to each of object in the array depending on the length of the array.
Here's my code so far
function updateObject(obj) {
let timeNow = new Date();
let addHours = (h) => timeNow.setHours(timeNow.getHours() + h);
const ids = obj.map((record) => record.id);
const lastNames = obj.map((record) => record.id);
const time = obj.map(
(record, index) => (record["time"] = new Date(addHours(index)))
);
return obj;
}
This returns:
[
{
firstName: 'Akira',
id: '0543236543',
time: 2021-05-18T12:25:59.366Z
},
{
firstName: 'Harry',
id: '0994372684',
time: 2021-05-18T13:25:59.366Z
},
{
firstName: 'Sherlock',
id: '0487345643',
time: 2021-05-18T15:25:59.366Z
},
{
firstName: 'Kristian',
id: '04873452342',
time: 2021-05-18T18:25:59.366Z
}
]
First issue: I want to update the time by adding 0,1,2,3 hours to the current time.
Currently it:
adds 0 to time and sets is a current time
adds 1 to updated time and set it a as a current time and so on.
Second:
I want to modify the function so it takes an add additional argument, "time increment" that if set to x will update the time property for first x records for 0 hours and the next x records for 1 hour.
Hope that makes sense :)
First issue can be solved by changing addHours to be a pure function that does not mutate timeNow:
const timeNow = Date.now();
const addHours = (h) => new Date(timeNow + h * 60 * 60 * 1000);
Second issue can be solved by looking at the index in the map:
const time = obj.map(
(record, index) => (record["time"] = new Date(addHours(index > increment ? 1 : 0))));
And in general, I would advise against mutating objects/arrays. Pure functions are usually easier to reason about and offer fewer surprises.
I would write the updateObject function so it does not mutate the original, but returns a new array with new objects.
Thanks! What if the increment parameter defines how many first x records should have the time property increased by 1h
For example my contacts array length is 4.
function updateObject(records, 1) {
\\code here
}
The first object would have the time property increased by 0h.
The second object would have the time property increased by 1h.
The third object would have the time property increased by 2h.
The fourth object would have the time property increased by 3h.
function updateObject(records, 3) {
\\code here
}
The first 3 objects would have the time property increased by 0h.
The fourth object would have the time property increased by 1h.
Do I need to slice the array into sub arrays first?

lodash filter map, array of object containing dates and formatting to MM/DD

I am trying to use lodash to map and filter an array of object containing dates like
[{date: '2020-09-15T04:43:15:2176807-04:00'},{date: '2020-09-15T04:43:15:2176807-04:00'},{date: '2020-09-15T04:43:15:2176807-04:00'}]
I am trying to achieve
['09/15', 09/15', '09/15']
I tried
const formated dates = this.states.data.filter(o => moment(o.date)).format('MM/DD'))
also tried something like this
const dates = _.map(
_.filter(o => moment(o.date)).format('MM/DD'))
)
but so far, unsuccessful.
Any help is appreciated. Thanks
The tricky part here is to parse your date, after that, things get easier
2020-09-15T04:43:15:2176807-04:00
YYYY-MM-DDTHH:mm:ss:SSSSSSSZZ
(for more detail on tokens, check the doc)
const data = [
{ date: "2020-09-15T04:43:15:2176807-04:00" },
{ date: "2020-09-15T04:43:15:2176807-04:00" },
{ date: "2020-09-15T04:43:15:2176807-04:00" },
]
const res = _(data)
.map("date")
.map((date) => moment(date, "YYYY-MM-DDTHH:mm:ss:SSSSSSSZZ").format("MM/DD"))
.value()
console.log(res)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.20/lodash.min.js"></script>
<script src="https://momentjs.com/downloads/moment.min.js"></script>

Compare two List of objects and once it matched then return list of objects in React JS

I am very new to ReactJs. I have one requirement to compare both lists and then matched objects should return as output. These comparison should based on unique keys in the object i.e id, endTime.
Please have a look into below code.
From the below two Lists , I need to compare both of them based on unique keys (id, endTime), once it is matched or equal then need to return those objects as list.
Please help me on this.
The selected/ matched objects should return as output.
const apiResponse = [
{
id: 5520437,
startTime: 1498665761714,
endTime: 1498665824487,
},
{
id: 5520436,
startTime: 1498665761714,
endTime: 1498665824488,
},
{
id: 5520435,
startTime: 1498665761714,
endTime: 1498665824489,
},
{
id: 5520434,
start Time: 1498665761714,
endTime: 1498665824490,
}
]
const mySelectedData = [
{
id: 5520437,
start Time: 1498665761714,
endTime: 1498665824487,
},
{
id: 5520436,
start Time: 1498665761714,
endTime: 1498665824488,
},
]
I hope this is what you were looking for. Im comparing both of list and if given element of apiResponse is also an item of selected Data - is added to the result list
const tada = apiResponse.reduce(
(result, item) =>
mySelectedData.some(el => el.endTime === item.endTime)
? [...result, item]
: result,
[]
);
codesandbox -> https://codesandbox.io/s/runtime-smoke-bywti?fontsize=14
You can use filter
function myCompartor(arr){
return function(c){
return arr.filter(function(o){
return o.id == c.id
}).length == 0;
}
}
var common = apiResponse.filter(mySelectedData(mySelectedData));

Resources