I'm trying to create an array of hours in a day with 30 minute intervals with moment.js and ES6.
Example:
let hours = ["12:00 AM", "12:30 AM", "1:00 AM", "1:30 AM", ..., "11:30 PM"]
I already have this for function:
someFunction () {
const items = []
for (let hour = 0; hour < 24; hour++) {
items.push(moment({ hour }).format('h:mm A'))
items.push(moment({ hour, minute: 30 }).format('h:mm A'))
}
return items
}
But I would like to make it more ES6-like.
I have gotten this far:
someFunction () {
let timeSlots = new Array(24).fill().map((acc, index) => {
let items = []
items.push(moment( index ).format('h:mm A'))
items.push(moment({ index, minute: 30 }).format('h:mm A'))
})
return timeSlots
}
But it outputs:
["1:00 AM", "12:30 AM", "1:00 AM", "12:30 AM", "1:00 AM", "12:30 AM", "1:00 AM", "12:30 AM", "1:00 AM", "12:30 AM", "1:00 AM", "12:30 AM", ...]
function someFunction () {
const items = [];
new Array(24).fill().forEach((acc, index) => {
items.push(moment( {hour: index} ).format('h:mm A'));
items.push(moment({ hour: index, minute: 30 }).format('h:mm A'));
})
return items;
}
You can use array#from with array#reduce to generate 30 minutes interval time.
let someFunction = () => {
return Array.from({length: 24}, (_,i) => i).reduce((r,hour) => {
r.push(moment({hour, minute: 0}).format('h:mm A'));
r.push(moment({hour, minute: 30}).format('h:mm A'));
return r;
}, []);
}
console.log(someFunction());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
here is working code:
someFunction = () => {
var items = []
var currentDate = moment('12');
new Array(48).fill().map((acc, index) => {
items.push(currentDate.format('h:mm A'))
currenDate = currentDate.add(30, 'minutes');
})
return items
}
console.log(someFunction());
Working fiddle: http://jsfiddle.net/ekqxhwf4/1/
You could use Array.from method to generate 2d array and then concat with spread syntax to create 1d array.
function create () {
return [].concat(...Array.from(Array(24), (_, hour) => ([
moment({hour}).format('h:mm A'),
moment({ hour, minute: 30 }).format('h:mm A')
])))
}
console.log(create())
<script src="http://momentjs.com/downloads/moment.js"></script>
I know momentJS was a requirement, but could also be easily solved with ordinary JavaScript Date objects:
function everyXMilliseconds(x) {
if (x === void 0) {
x = 86400000;
}
var base = new Date(86400000);
var currentDate = new Date(86400000);
var dates = [];
while (currentDate.getUTCDate() === base.getUTCDate()) {
dates.push(new Date(currentDate.getTime()));
currentDate.setTime(currentDate.getTime() + x);
}
return dates;
}
function everyXSeconds(x) {
if (x === void 0) {
x = 86400;
}
return everyXMilliseconds(x * 1000);
}
function everyXMinutes(x) {
if (x === void 0) {
x = 1440;
}
return everyXSeconds(x * 60);
}
function everyXHours(x) {
if (x === void 0) {
x = 24;
}
return everyXMinutes(x * 60);
}
//Offsets date with its own timezone difference
function toLocalTime(date) {
date.setUTCHours(date.getUTCHours() + date.getTimezoneOffset() / 60);
return date;
}
//TEST
//get dates
var dates = everyXHours(0.5);
// dates to time
console.log('UTC times', dates.map(function(d) {
return d.toLocaleTimeString("uk");
}));
// dates to time localized
console.log('Local times', dates.map(toLocalTime).map(function(d) {
return d.toLocaleTimeString("uk");
}));
My snippet above is bit overly complicated, but it illustrates that you can make really flexible system without need to import libraries.
you can get the value with the label.
function someFunction () {
const items = [];
new Array(24).fill().forEach((acc, index) => {
items.push({"value": moment( {hour: index} ).format('HH:mm'), "label": moment( {hour: index} ).format('h:mm A')});
items.push({"value": moment({ hour: index, minute: 30 }).format('HH:mm'), "label": moment({ hour: index, minute: 30 }).format('h:mm A')});
})
return items;
}
An even shorter version would be:
const someFunction = () =>
Array(48)
.fill()
.map((_, index) =>
moment({
hour: Math.floor(0.5 * index),
minute: 30 * (index % 2)
})
.format("h:mm A"));
Related
i want to get the list of next week days in given format "March 12 Sunday" and then convert that is final list of week days as given below.
Here is a my current code with which i am trying to get desire output but that returns "06/12/22" format..
Current code :
const nextWeek = [...Array(7).keys()].map(days => new Date(Date.now() + 86400000 * days).toLocaleDateString('en-us', { weekday:"long", month:"short", day:"numeric"}))
console.log("== > ",nextWeek)
current output :
["09/17/22", "09/18/22", "09/19/22", "09/20/22", "09/21/22", "09/22/22", "09/23/22"]
first i want this output
["Sunday, March 4", "Monday, March 4", "Tuesday, March 4", "Wednesday, March 4", "Thursday, March 4", "Friday, March 4", "Saturday, March 4"]
and then final desire output is:
const nextWeekdata = [
{ id: 1, name: "Sunday" ,date:21,Month:"March" },
{ id: 2, name: "Monday" ,date:22,Month:"March" },
{ id: 3, name: "Tuesday" ,date:23,Month:"March" },
{ id: 4, name: "Wednesday" ,date:24,Month:"March" },
{ id: 5, name: "Thursday" ,date:25,Month:"March" },
{ id: 6, name: "Friday" ,date:26,Month:"March" },
{ id: 7, name: "Saturday" ,date:27,Month:"March" },
];
If you want to calculate the range of dates for next week, break your logic into smaller chunks.
You should have three functions:
Function that gets the date for a given day of the week; next week
Function that gets the range of all the dates next week
Function to map the dates to object data
const getNextDay = (dayIndex) => {
const today = new Date();
today.setDate(today.getDate() + (dayIndex - 1 - today.getDay() + 7) % 7 + 1);
return today;
};
const getNextWeek = () => [...Array(7).keys()].map(getNextDay);
const nextWeek = getNextWeek().map((date, index) => ({
id: index + 1,
name: date.toLocaleDateString('en-us', { weekday: 'long' }),
date: date.getDate(),
month: date.toLocaleDateString('en-us', { month: 'long' }),
year: date.getFullYear()
}));
console.log(nextWeek);
.as-console-wrapper { top: 0; max-height: 100% !important; }
const nextWeek = [...Array(7).keys()].map((days) =>
new Date(Date.now() + 86400000 * days).toLocaleDateString("en-us", {
weekday: "long",
month: "short",
day: "numeric",
})
);
let newArray = [];
nextWeek.forEach((item, index) => {
let data = item.split(",");
let secondLength = data[1].length;
newArray.push({
id: index + 1,
name: data[0],
date: data[1].substring(secondLength - 2),
month: data[1].substring(1, secondLength - 3),
});
});
console.log("days", newArray);
does this work? yes
is this the right way to do it? nope
is this the easy way? for me, it is.
Actually, when I use your current code I get this as a result:
(7) ['Saturday, Sep 17', 'Sunday, Sep 18', 'Monday, Sep 19', 'Tuesday, Sep 20', 'Wednesday, Sep 21', 'Thursday, Sep 22', 'Friday, Sep 23']
Which means it works as you wish; what browser are you using?
Regarding the Second Question of yours, I'd have used something such as this:
class weekDay {
constructer(id, x) {
let name = x.split(", ")[0];
let day = x.split(", ")[1].split(" ")[1];
let month = x.split(", ")[1].split(" ")[0];
this.id = id;
this.name = name;
this.day = day;
this.month = month;
}
}
const nextWeek = [...Array(7).keys()].map(days => new Date(Date.now() + 86400000 * days).toLocaleDateString('en-us', { weekday:"long", month:"long", day:"numeric"}))
var arr = [];
for (let i=0; i<=6; i++) {
arr.push(new weekDay(i+1, nextWeek[i]));
}
This is my way of doing it, but take heed that I haven't tested it so it might have some syntax errors, if there was any, please notify me.
I have a date with a time, like this
const date = {year: 2020, month: 12, day: 31};
const time = {hours: 16, minutes: 2};
How do I get UTC representation of that time depending on a timezone?
(without using any libraries)
convetToUTC(date, time, "Europe/Moscow") // => <UTC timestamp>
convetToUTC(date, time, "America/New_York") // => <UTC timestamp>
Examples
convetToUTC(
{year: 2021, month: 7, day: 30},
{hours: 16, minutes: 15},
"Europe/Moscow"
) // => 1627650900
convetToUTC(
{year: 2021, month: 7, day: 30},
{hours: 16, minutes: 15},
"America/New_York"
) // => 1627676100
Piggy-backing on Achempion's response, I fixed the timezone offset calculation. The timezone date should be subtracted from the UTC date. The result of this difference should be in minutes.
You will need to then convert the minute offset back into milliseconds and subtract this from the date.
/**
* Calculates the timezone offset of a particular time zone.
* #param {String} timeZone - a database time zone name
* #param {Date} date - a date for determining if DST is accounted for
* #return {Number} returns an offset in minutes
* #see https://stackoverflow.com/a/68593283/1762224
*/
const getTimeZoneOffset = (timeZone = 'UTC', date = new Date()) => {
const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' }));
const tzDate = new Date(date.toLocaleString('en-US', { timeZone }));
return (tzDate.getTime() - utcDate.getTime()) / 6e4;
}
const defaultDateConfig = { year: 0, month: 0, date: 0 };
const defaultTimeConfig = { hours: 0, minutes: 0, seconds: 0 };
const convetToUTC = (dateConfig, timeConfig, timeZone) => {
const { year, month, date } = { ...defaultDateConfig, ...dateConfig };
const { hours, minutes, seconds } = { ...defaultTimeConfig, ...timeConfig };
const d = new Date(Date.UTC(year, month - 1, date, hours, minutes, seconds));
const offsetMs = getTimeZoneOffset(timeZone, d) * 6e4;
return (d.getTime() - offsetMs) / 1e3;
};
// Main
const date = { year: 2021, month: 7, date: 30 };
const time = { hours: 16, minutes: 15 };
console.log(convetToUTC(date, time, 'America/New_York')); // 1627676100
console.log(convetToUTC(date, time, 'Europe/Moscow')); // 1627650900
const dateWithTimeZone = (timeZone, year, month, day, hour, minute, second) => {
let date = new Date(Date.UTC(year, month, day, hour, minute, second));
let utcDate = new Date(date.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(date.toLocaleString('en-US', { timeZone: timeZone }));
let offset = utcDate.getTime() - tzDate.getTime();
date.setTime( date.getTime() + offset );
return date;
};
dateWithTimeZone("America/New_York", 2021, 7 - 1, 30, 16, 15, 0).getTime() / 1000)
// => 1627676100
dateWithTimeZone("Europe/Moscow", 2021, 7 - 1, 30, 16, 15, 0).getTime() / 1000)
// => 1627650900
7 - 1 used to illustrate that function accepts month's index, not month's number
There will be 2 inputs for dates and the output should look like this.
Assume that 2 inputs are 2020-01-01 and 2020-02-23
{
"2021-01" : 31,
"2021-02" : 23,
}
And the second thing is, if a month includes all its days, it should be represented as:
{
"2021-01" : {
days: 31,
isAll : true
},
"2021-02" : {
days: 23,
isAll : false
},
}
How could I do that?
You can use .reduce to iterate over the object entries, and for each key, save an object of the number of days and whether it is the last day:
const _getLastDay = date => {
const [year, month] = date.split('-');
return new Date(year, month, 0).getDate();
}
const getDates = (date1, date2) => {
const data = {
[`${date1.getFullYear()}-${('0'+(date1.getMonth()+1)).slice(-2)}`]: date1.getDate(),
[`${date2.getFullYear()}-${('0'+(date2.getMonth()+1)).slice(-2)}`]: date2.getDate()
};
return Object.entries(data).reduce((acc, [date,days]) => {
acc[date] = { days, isAll: _getLastDay(date)===days };
return acc;
}, {});
}
console.log( getDates(new Date("2021-01-31"),new Date("2021-02-23")) );
I am facing an issue in React JS. I want to do compare or match the start_date with header date
Rest API
[
{
"id": "1",
"staff_name": "Jill",
"custom_service_name": "Jone",
"start_date": "2020-05-06 11:30:00",
"end_date": "2020-05-06 11:45:00",
},
{
"id": "2",
"staff_name": "james",
"custom_service_name": "smith",
"start_date": "2020-05-06 11:00:00",
"end_date": "2020-05-06 11:15:00",
}
]
console.log data:
1:00 AM //start_date
["9:43:36 AM", "9:13:36 AM", "10:13:36 AM"] //header_date
12:00 PM
["9:43:36 AM", "9:13:36 AM", "10:13:36 AM"] //header_date
2:15 AM
["9:43:36 AM", "9:13:36 AM", "10:13:36 AM"] //header_date
My Code:
var currentdate = new Date(); //header_date logic
var prevdate = new Date();
var firstdate = new Date();
prevdate.setTime(currentdate.getTime() - (30 * 60 * 1000));
firstdate.setTime(currentdate.getTime() + (30 * 60 * 1000));
var current = currentdate.toLocaleTimeString();
var previous = prevdate.toLocaleTimeString();
var first = firstdate.toLocaleTimeString();
var headerdate = [previous ,current, first];
this.state = {
headerdate:headerdate,
appointmentdata:[]
}
componentDidMount() { //get start_date
axios.get(`http://localhost/route/v1/appointment`)
.then(res => {
const appointmentdata = res.data;
console.log(appointmentdata);
this.setState({ appointmentdata });
})
}
I try , but this logic is not working
render() { return (
<div>
{this.state.appointmentdata.map(data =>
{ const dateTime = moment(data.start_date.toString());
if (dateTime.format("h:mm A") === this.state.headerdate)
{
return <p>{dateTime.format("h:mm A")}</p>; } //return the match date
else { return null; } })}
Demo:
https://codesandbox.io/s/quizzical-browser-9e3g4
What should i do?
Can anyone help me
I see you're using Moment. So you can use isSame built-in helper from them to achieve this.
Docs: https://momentjs.com/docs/#/query/is-same/
Example code:
const isSameDate = (start_date, header_date) => {
const startDate = moment(start_date);
const headerDate = moment(header_date);
return startDate.isSame(headerDate, 'day');
}
One small tip, you should move the date checking outside the render method, that would makes your code easier to read and maintainable
const arr = [
{
"date": "2019-09-18"
},
{
"date": "2019-09-19"
},
{
"date": "2019-09-21"
},
{
"date": "2019-09-22"
},
{
"date": "2019-09-23"
}
]
function currentStreak(arr) {
let count = 0
arr.reverse().forEach((el, i) => {
if (new Date() - new Date(el.date) === i * 86400000) count++
})
return count
}
I'm having a hard time getting this to work. Assuming the current date is "2019-09-23", why is the above code returning 0 when it should return 3?
You are passing the current Date i.e today's date - 5th Nov Tue so the calculation done is on the basis of today's date, you must pass the value of date object
For example :-
const arr = [
{
"date": "2019-09-18"
},
{
"date": "2019-09-19"
},
{
"date": "2019-09-21"
},
{
"date": "2019-09-22"
},
{
"date": "2019-09-23"
}
]
function currentStreak(arr) {
let count = 0
arr.reverse().forEach((el, i) => {
if (new Date('2019-09-23') - new Date(el.date) === i * 86400000) count++
})
return count;
}
console.log(currentStreak(arr))
Since, new Date() gives you date + current time, hence it cannot compare correctly with the New Date(YYYY-MM-DD) which gives time at midnight hours.
If you modify your date to midnight hours, then it will compare correctly. So your code will look like.
function currentStreak(arr) {
let count = 0
arr.reverse().forEach((el, i) => {
if ((new Date().setUTCHours(0,0,0,0) - new Date(el.date).setUTCHours(0,0,0,0)) === i * 86400000) count++
})
return count
}
new Date() returns this - Tue Nov 05 2019 15:16:22 GMT+0800 (Singapore Standard Time)
So in your if condition it will not increment. Change the format of the new Date() and compare it to your array.
const arr = [
{
"date": "2019-09-18"
},
{
"date": "2019-09-19"
},
{
"date": "2019-09-21"
},
{
"date": "2019-09-22"
},
{
"date": "2019-09-23"
}
]
function currentStreak(arr) {
let count = 0
arr.reverse().forEach((el, i) => {
if ((new Date() - new Date(el.date) >= i * 86400000) && (new Date() - new Date(el.date) < (i+1) * 86400000)) count++
})
return count
}
console.log(currentStreak(arr));
It doesn't work because you didn't include minutes, hours, seconds and milliseconds.