Assume I have two time values as startTime and endTime.
I want to find the exact mid value of this time objects.
Example: if startTime is 10:30 and endTime is 11:30, I need 11:00 as the midpoint value.
How to solve this using momentjs in JavaScript?
The middle between two dates is just half of the difference between the dates added to the smaller one.
The difference should be pretty straight forward:
Math.abs(moment(a).diff(b))
Math.abs() removes the minus from negative numbers (aka if a < b).
Calculating the middle has two steps too, first divide the difference by two, then add it to the smaller date (Math.min()):
diff/2+Math.min(moment(a).valueOf(),moment(b).valueOf())
moment(n).valueOf() turns your Date strings into comparable integers.
function middleDate(a,b) {
let diff = Math.abs(moment(a).diff(b))
let middle = diff/2+Math.min(moment(a).valueOf(),moment(b).valueOf())
return moment(middle)
}
console.log(middleDate("2022-01-27T10:30:00Z", "2022-01-27T11:30:00Z"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
If you only want the hours and minutes, you can just format the returned moment object (and use moment.utc() to remove the timezone):
function middleDate(a,b) {
let diff = Math.abs(moment(a).diff(b))
let middle = diff/2+Math.min(moment(a).valueOf(),moment(b).valueOf())
return moment(middle)
}
console.log(
moment.utc(middleDate("2022-01-27T10:30:00Z", "2022-01-27T11:30:00Z")).format("hh:mm")
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
Here is how i solved it
(For my particular case that deals with time only. For more generic cases, you can use the answer above)
import moment from 'moment';
export const middleDate = (startTime, endTime) => {
let duration = moment.duration(moment(endTime, 'HH:mm:ss').diff(moment(startTime, 'HH:mm:ss'))); //get Total Interval
let midInterval = duration.asHours() / 2; // find half of the interval
return moment(moment(startTime, 'HH:mm:ss')).add(midInterval, 'hour').format('HH:mm'); //add the mid interval to the startTime we have
};
Related
I have a time span between two epoch times (in seconds). I want a function that returns the epoch times (in seconds) of all midnights within that time span.
In pseudocode I would want something like this:
const epoch_start = 1600000;
const epoch_end = 16040000;
function getMidnights(start, end){
// do your magic
}
console.log(getMidnights(epoch_start, epoch_end));
I would expect the return of that function to look like this: [1600020, 1600400] (these are just example values).
What would be the most efficient way to do this?
My ideas were: get unique list of days within range and return their midnight.
You might step by day rounding by day:
const epoch_start = 1600000000;
const epoch_end = 1600400000;
const day = 86400;
function getMidnights(start, end){
midnites = [];
while (start < end) {
midnites.push((start/day + .5|0)*day);
start += day;
}
return midnites;
}
console.log(getMidnights(epoch_start, epoch_end))
console.log('* check it *')
console.log(getMidnights(epoch_start, epoch_end).map(t => new Date(t*1e3)));
I've divided a day into 8 ticks of three hours each. When making this range it goes from 00:00 to 21:00, and not until 00:00 again.
const startDate = new Date("2021-03-14T23:00:00.000Z");
const endDate = new Date("2021-03-15T23:00:00.000Z");
const dayInThreeHourPeriods = d3.timeHour.every(3).range(startDate, endDate);
dayInThreeHourPeriods.forEach((period) => {
console.log(`period: ${format(period, 'HH:mm')}`);
});
// outputs
// from: 00:00
// to: 21:00
// would like it to go to 24:00
How can I change this so that it goes to 24:00?
I want to use it for an axis:
Made a working example here: https://jsfiddle.net/Spindle/kfL5oh12/21/
This is intended from the .range method, as d3.timeHour.every is just an alias to interval.range;
From d3-time docs:
interval.range(start, stop[, step]) ยท Source
Returns an array of dates representing every interval boundary after or equal to start (inclusive) and before stop (exclusive). If step is specified, then every stepth boundary will be returned; for example, for the d3.timeDay interval a step of 2 will return every other day. If step is not an integer, it is floored.
As you've already stated in your own answer, it seems like a known issue.
Anyway, why don't use write your own logic to divide the day into 3-hours chunks? This way we don't need to rely on d3d3's .range method;
let startDate = new Date("2021-03-14T23:00:00.000Z");
let endDate = new Date("2021-03-15T23:00:00.000Z");
var dayInThreeHourPeriods = [ startDate ];
while (endDate > startDate) {
startDate = new Date(startDate.getTime() + (60 * 60 * 3 * 1000));
dayInThreeHourPeriods.push(startDate);
}
console.log(dayInThreeHourPeriods);
Updated JSFiddle
Turns out this is a known issue.
What people tend to do is add a small time period and suddenly it's inclusive:
d3.range(min, max+0.001)
or in my case:
const dayInThreeHourPeriods = d3.timeHour.every(3).range(startDate, d3.timeHour.offset(endDate, 1));
Not ideal. Look there's a proposal to have 'rangeInclusive' which would be better already. But there is no activity on that issue.
If anyone has a better idea for the time being I'd be interested.
I need to compare two values, as you see in my code below.
Point is that they are in different formats, and i need them to compare.
Here is my code(daysToLeave is allways number 1-3 - this value match 1-3 days):
const tomorrow = new Date();
const tmp = tomorrow.getDate() + daysToLeave;
tomorrow.setDate(tmp);
console.log("eventDate.date", eventDate?.date);
console.log("tommorrow", tomorrow);
if (eventDate?.date < tomorrow) {
console.log("success");
}
Here are my console.logs:
use moment and .diff().
//Determine the unit of difference between
const type = ["years","months","weeks","days","hours","minutes"]
moment(tomorrow).diff(eventDate?.date.toDate(), type[3])
Hey I'm trying to calculate user age using Moment.
function getAge(birthDate) {
const start = moment(birthDate, "YYYY-MM-DD");
const end = moment();
return start.to(end, true);
}
Before the month of may, the result is 1 year over:
getAge("1989-01-01"); // 31 years
getAge("1989-05-01"); // 30 years
example: https://codesandbox.io/s/nostalgic-tesla-bzb3d
the behavior is the same using fromNow instead of to
do you have any idea on how to solve this?
The result of .to() is a relative time string and it internally rounds the values in either direction (so 29.5 years would become 30 years). It is meant for display purposes like showing "posted 3 minutes ago" in forum or blog posts.
You are looking for the .diff() method that calculates the difference, but will only account for full units of measurement provided by the second argument, i.e. truncating the actual number.
const start = moment(birthDate, "YYYY-MM-DD");
age = moment().diff(start, "years");
https://codesandbox.io/s/naughty-lewin-e6vrt
You may use diff function like:
function getAge(birthDate) {
const start = moment(birthDate, "YYYY-MM-DD");
const end = moment();
return end.diff(start, 'years');
}
console.log(getAge("1989-01-01"));
console.log(getAge("1989-05-01"));
I have a method that accepts a javascript date with time as input, and determines if the current date and time is within -30 mins. However, when I debug this at runtime, moment.add doesn't seem to be working with minutes as expected.
function isWithinRange(myDate: Date){
// convert to Moment obj
let myMoment = moment(myDate);
let todayMoment = moment(new Date());
let myMomentOk = myMoment.isValid();
let todayOk = todayMoment.isValid();
// create range values
let preTime = myMoment.subtract('m', 30);
let postTime = myMoment.add('m', 30);
//check values are as expected
let localeTime = myDate.toLocaleString();]
let preLocale = preTime.toLocaleString();
let postLocale = postTime.toLocaleString();
let result = todayMoment.isBetween(preTime, postTime);
return result;
}
But when I inspect the localeTime, preLocale and postLocale times at run time, all three values are the same, "Tue Jun 26 2018 09:58:00 GMT-0400". The add and subtract minutes statements had no impact.
What am I missing or doing wrong here?
Please note that both add() and subtract mutate the original moment.
add():
Mutates the original moment by adding time.
subtract:
Mutates the original moment by subtracting time.
so you have to use clone()
Moreover, in the recent version of moment, the first argument is the amount of time to add/subtract and the second argument is the string that represent the key of what time you want to add
add and subtract takes the amount of time first, and then what type of time, as documented here. Also make sure to create a new moment object for each calculation, as it mutates the moment object.
let preTime = moment(myMoment).subtract(30, 'm');
let postTime = moment(myMoment).add(30, 'm');
You're working on the same moment object all the time, because of this you have the original moment object at the time you're doing let localeTime = myDate.toLocaleString().
You just need to create a new moment object so you don't revert your changes.
...
// create range values
let preTime = moment(myMoment).subtract('m', 30);
let postTime = moment(myMoment).add('m', 30);
...
I think what you need to use is https://momentjs.com/docs/#/query/is-between/ isBetween method from the moment.
const testDate = moment()
testDate.isBetween(moment().subtract(30, 'm'), moment().add(30, 'm'))
// true
const testDate = moment().add(2, 'h');
testDate.isBetween(moment().subtract(30, 'm'), moment().add(30, 'm'))
// false
I think this should help.