How to display Hourly data based on Current Time? - javascript

I have two values, one from Hourly data and other from Current Time, where its hour is to be compared and display when found match or equal
See below code for better understanding
export class HourlyForecast extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
const { data } = this.props;
if(!data) return null;
const time = data.datetime
const time2 = time.slice(11,13)
console.log('HOURLY DATA', time2)
const time5 = moment.tz(this.props.timezone).format('HH:mm').slice(0,2)
console.log('TIME CURRENT', time5);
}
}
export default HourlyForecast
I want to compare the hour value from hourly data with current time's hour value. How to do it?
See the above image for reference. The Hourly data ranges from 00 to 09 whereas Current Time is 02. The Hourly data must display from 02 comparing with Current Time.

Question is not clear though you can try this to compare.
async function1(){
let hourData = await hourlyfunction()
let currentData await currentTimefunction()
return hourData==currentData
}

Related

LWC Date input Calculator

I am trying to get a correct outcome on difference of two dates. But when I do this I am getting a result such as (ex.10211438742389) instead of 1, 2, 3, 4, etc.. This is my JavaScript code.
import Division from '#salesforce/schema/User.Division';
import { LightningElement, track } from 'lwc';
export default class LightningExampleInputDate extends LightningElement {
#track date1;
#track date2;
#track result;
datehandler1(event) {
this.date1 = Date.now();
console.log(event.target.value)
}
datehandler2(event) {
this.date2 = new Date(event.target.value);
console.log(event.target.value);
}
resulthandler() {
this.result = Math.abs(this.date2 - this.date1);
console.log(this.result);
}
}
I am expecting a shorter value to come out when I check the difference in-between two dates.
Dates in javascripts is a representation of milliseconds starting from the epoch date, which is 1st of Jan 1970.
If you want to calculate the difference of two dates in days, you could try this solution: https://stackoverflow.com/a/3224854/1964104

Array inside useEffect to use in if Statement

I'm trying to use an if statement in my code where I want it to 'open' a Calendar Box if the date of today has occurred as well as for the past days of my calendar to open.
Here is my code where I'm using an useEffect to post it on loading the React Component:
// Call on post method via axios
useEffect(async () => {
console.log(daysData);
const daysDay = daysData.map((day) => day.day);
console.log(daysDay);
if (date + 1 >= daysDay) {
// Url where to post
await axios.post(`http://localhost:5001/open/chocolate`, {
day: date,
});
alert('New day is available to eat!');
}
setOpenCalendarBox('');
}, []);
I'm trying to get an array I've initiated a few lines above of the useEffect function (daysData) and I want the value of the 'day' item inside of the objects inside of the array and then compare the date of today if it is equal to or less than daysDay (day item inside of daysData)
Here is the code for my array:
// Here I initalize the array with useState
const [daysData, setDaysData] = useState([]);
// Here is the port I'm fetching my array from.
useEffect(() => {
fetch('http://localhost:5001/chocolates')
.then((resp) => resp.json())
.then((data) => setDaysData(data));
}, []);
And here is the date code:
// Initiate new Date
const current = new Date();
// Retrieve current day of the month
const date = current.getDate();
I can't seem to get the effect I want. I basically only want to see if the day has passed or if it is today then I want it to post to '/open/chocolate'.
That's probably because the value of daysData is set asynchronously, yet the useEffect block that depends on it does not list it as a dependency. Therefore you are invoking logic, which requires daysData to be populated asynchronously, when the component is loaded at runtime. So daysData will be empty.
A solution is to simply add daysData in the dependency array, so that you will only execute whatever logic that is in there once the array is successfully populated.
On the other hand, you are comparing a number against an array: which will give an unexpected result. If you want any of the day to meet date + 1, use daysDay.some(d => date + 1 >= d). If you want all of the days to meet date + 1, use daysDate.every(d => date + 1 >= d).
useEffect(async () => {
const daysDay = daysData.map((day) => day.day);
// This needs to be fixed, see comment for options
if (daysDay.some(d => date + 1 > d)) {
// Url where to post
await axios.post(`http://localhost:5001/open/chocolate`, {
day: date,
});
}
setOpenCalendarBox('');
}, [daysData]);

How can I make the value of selected time as a range of hours in React

I want the value of selected times to be as a range as, (11:00am - 12:00pm) then the second value to be as (12:00pm - 01:00pm) and so on.
As shown here in the first time value
I am using ReactTimePicker from react-ts-timepicker package.
<ReactTimePicker
value={this.state.selectedTime} //I want here to be as range
minTime={this.state.minTime} //09:00am
maxTime={this.state.maxTime} //09:00pm
step={60}
onChange={this.handleChangeTime}
allowOnlySuggestions
className="future-order-time-input"
/>
handleChangeTime = (e) => {
//To get the format I want (hour,minutes,am/pm)
let timeResult = this.parseTime(e, null);
let time = this.getTime(timeResult);
this.setState({ selectedTime: time });
};

date-fns and react - while loop adds 1 more day after checking given if statement condition

I created a Calendar with React hooks, using date-fns,
following this article -> https://medium.com/#w.difulvio523/create-a-custom-hooks-calendar-in-react-e50bbba456e1
And added the functionality to display schedules which I fetch from my backend.
The logic is, if the schedule objects date is same as the cloneDay,
render the extra Link element where user can click and go to the matching schedule page.
The problem is that the schedule is being render on actual schedule day + 1.
ex. if the date is 14th, it will render on 15th
this issue is happening inside of the cell function
const cells = () => {
const monthStart = startOfMonth(currentDate)
const monthEnd = endOfMonth(monthStart)
const startDate = startOfWeek(monthStart, {weekStartsOn: 1})
const endDate = endOfWeek(monthEnd)
const dateFormat = "d"
const rows = []
let days = []
let day = startDate
let formattedDate = ""
//here get the schdules
//and render in cells.
//if the schduels.date is same as 'day' or 'clone day',
//render <Link/> to Exercise element with corresponding ID
while (day <= endDate) {
for (let i = 0; i < 7; i++) {
formattedDate = format(day, dateFormat)
const cloneDay = day
//split and reforamt the cloneDay to compare with schedule object's date
const formatCloneDay = cloneDay.toISOString().split('T')[0]
// console.log('formatCloneDay', formatCloneDay)
const scheduleElements = exerciseScheduleArray.map(schedule => {
//reformat for the compare with formatCloneday
const formatScheduleDate = schedule.date.split('T')[0]
const hasMatchingDays = formatScheduleDate.toString() === formatCloneDay.toString()
if(hasMatchingDays) {
//here it adds 1 day from matching day
return (
<Link className="schedule-link" to="/exercise/:exerciseId" key={schedule._id}>
<span>{schedule.bodySection} {schedule.duration}</span>
</Link>
)
}
else return null
})
days.push(
<div
className={`column cell ${
!isSameMonth(day, monthStart) ? "disabled" :
isSameDay(day, selectedDate) ? "selected" : "" }`}
key={day}
onClick={() => onClickDate(cloneDay)}
>
<span className="number">{formattedDate}</span>
<span className="bg">{formattedDate}</span>
{hasSchedules ? scheduleElements : null}
</div>
)
//this will increase the day value by 1 each time it iterates
day = addDays(day, 1)
}
rows.push(
<div className="row" key={day}> {days} </div>
)
//if 7 days has been pushed to the rows, delete the days
//so it could start a new row with new days
days = []
}
return <div className="body">{rows}</div>
}
I track down the 'cloneDay' value and this +1 behaviour happens inside of the if statement
where it checks the hasMatchingDays. Specifically here in .map function.
const scheduleElements = exerciseScheduleArray.map(schedule => {
//reformat for the compare with formatCloneday
const formatScheduleDate = schedule.date.split('T')[0]
const hasMatchingDays = formatScheduleDate.toString() === formatCloneDay.toString()
if(hasMatchingDays) {
//here it adds 1 day from matching day
return (
<Link className="schedule-link" to="/exercise/:exerciseId" key={schedule._id}>
<span>{schedule.bodySection} {schedule.duration}</span>
</Link>
)
}
else return null
})
I wonder why it is causing that +1 day, and how can I render the schedule on correct date?
_
exerciseScheduleArray looks like this
After a long search,
I found the issue regarding date-fns UTC timezones.
As mentioned in this thread,
https://github.com/date-fns/date-fns/issues/376
this might be the reason why the cell function would render schedules in correct date in USA, or same timeszones,
and would render day + 1, in t.ex Berlin.
For now, I will switch to moment.js to re-create the cell function as a solution.
Hope this helped ppl who encountered same issue as I did.

How to filter last day in an array?

I have an array of objects like this:
[
{
created: "2019-08-14T13:24:36Z",
email: "test1#gmail.com"
},
{
created: "2019-08-15T13:24:36Z",
email: "test2#gmail.com"
},
{
created: "2019-08-16T13:24:36Z",
email: "test1#gmail.com"
},
{
created: "2019-08-22T13:24:36Z",
email: "test4#gmail.com"
},
{
created: "2019-08-22T15:29:66Z",
email: "test1#gmail.com"
}
]
The array is sorted by created. I want to filter those records which are on the last day, irrespective of the time on that day. I added the timestamp using moment.js. Something on these lines:
router.get('/GetLastDayRecords', (req, res) => {
res.json(allRecords.filter(record => record.created.max()));
});
Split the task: first get the maximum date which you'll find at the end of the sorted array (just getting the "YYYY-MM-DD" part of it is enough) and then launch the filter:
let max = allRecords.length ? allRecords[allRecords.length-1].created.slice(0,10) : "";
res.json(allRecords.filter(({created}) => created >= max));
First you need to figure out which day is the last day. If you can assume the records are already sorted, then this is pretty simple:
// Assuming your records are stored in the variable "records"
var lastDay = records[records.length - 1].created;
Now here's where your specific answer may differ based on how you want to handle time zones. Suppose one event happened at 11 PM EST (3 AM GMT) and another event happened at 1 AM EST (5 AM GMT). Are these the same day? In Europe they are, but in America they aren't!
What you need to do is create some cipher from the date+time listed to a "day". This way you can compare two "days" to see if they're the same:
lastDay = new Date(lastDay);
// Setting hours, minutes, and seconds to 0 will give you just the "day" without the time, but by default will use the system timezone
lastDay.setHours(0);
lastDay.setMinutes(0);
lastDay.setSeconds(0);
Once you know which day was the last, it's a simple filter:
// Using a for loop
var results = []
for (var i = 0; i < records.length; i++)
{
if (records[i].created > lastDay) {
results.push(records[i]);
}
}
// Using .filter
var results = records.filter(x => x.created > lastDay);
Alternatively, since we know it's already sorted, we can do it a bit more efficiently by binary searching for the first record on the last day, then grabbing all records after that:
var test = records.length / 2;
var step = records.length / 4;
var found = false;
while (!found) {
if (records[test].created < lastDay) {
test += step;
step /= 2;
}
else if (records[test].created > lastDay) {
if (step == 1) {
// We found the exact cut-off
found = true;
}
else {
test -= step;
step /= 2;
}
}
}
var results = records.slice(test);
Because you're only interested in the "last" day, the logic is a bit simpler. If you wanted the "third" day, you would need to check if created was after the start of the third day and before the end of the third day. We can just check if it's after the start of the last day.
I would create a function to turn your created properties into data be easily compared.
I would also avoid trying to do the entire filter operation in one or two lines as it will difficult to read by other developers.
const dateToInt = date => parseInt( date.split('T').shift().replace(/-/g, '') );
The above will:
Split your created property into an array of date and time.
Select the first element, which happens to be the date.
Remove the dashes in the date.
Coerce the value into a number.
With this you can find the maximum value and filter based on that value.
const nums = foo.map( ({ created }) => dateToInt(created) )
First get a list of numbers from the dataset.
const max = Math.max( ...nums )
Get the biggest number in the list.
const lastDays = foo.filter( ({ created }) => dateToInt(created) === max )
With all that setup, getting the max date is very easy and readable.
Of course, since the list is already sorted. You could have just done this as well.
const last = foo[foo.length -1].created;
const lastDays = foo.filter( ({ created }) => created === last )
I wrote a solution using reduce and filter:
const lastDay = arr.reduce((acc, el) => {
const date = el.created.substr(0,10);
const oldDate = new Date(acc);
const nextDate = new Date(date);
if(oldDate.getTime() > nextDate.getTime()) {
return oldDate;
} else {
return nextDate;
}
}, '1900-01-01');
const lastDayArr = arr.filter(el => {
const date = el.created.substr(0,10);
const oldDate = new Date(lastDay);
const nextDate = new Date(date);
return (oldDate.getTime() === nextDate.getTime());
});
First, you find the most recent date, reducing the original array by comparing which date is the most recent, for this you drop the part of the created string that specifies the hours/minutes/seconds.
You can use a very distant in time date as initial value, or you can set it to null and add another validation in your callback function.
As a second step, you use filter, using the same technique of dropping the hours/minutes/seconds of the created string.
The end result is an array of the elements with the most recent date in your original array.
If you can assume the array is sorted, you can skip the reduce method and just do:
const lastDay = arr[arr.length - 1].created.substr(0,10);
This should work:
allRecords.filter( record => {
let last_date = allRecords[ allRecords.length - 1].created
return last_date.slice(0, 10) === record.created.slice(0, 10)
})
Basically, you are getting the last element from your array and slicing its created value down to its date. Then you are slicing your current record's created value down to its date and comparing if they are the same.
Assuming that the array is already ASC ordered:
const onLastDay = values.filter( v => {
const last = moment(values[ values.length - 1 ].created)
const differenceInDays = last.diff(moment(v.created), 'days')
return differenceInDays < 1
})
console.log(onLastDay)
NOTE: If you try with the reported array you get an error due the fact that the last date is not valid! There are 66 seconds!

Categories

Resources