moment - Issue with fromNow - javascript

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"));

Related

Find the mid time value between two time values using momentjs

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
};

having trouble with luxon, calculating time difference between 2 dates

kind people of StackOverflow, I'm having a problem with luxon (I guess I set it up wrong or did something wrong with it), right now it can't calculate future dates (says NaN), and for past dates take years into account so you get something like this:
[
what I want this code to do is focus on month and day (forget about the year) and if the passed date is 7 days away or is less than 7 days away from today's date say "the passed date is <= a week", later this will trigger a notifier, that will notify me a week in advance of my friends & families bdays.
the code:
const isBirthdayThisWeek = (birthDate) => {
const endDate = DateTime.now()
const startDate = DateTime.fromISO(birthDate)
const interval = Interval.fromDateTimes(startDate, endDate)
const dateDifference = interval.length('days')
const wholeNumberedDateDifference = Math.round(dateDifference)
wholeNumberedDateDifference <= 7
? console.log('bday is in less than a week', wholeNumberedDateDifference)
: wholeNumberedDateDifference > 7
? console.log('bday is more than in a week', wholeNumberedDateDifference)
: console.log('something went wrong', wholeNumberedDateDifference)
}
Thank you all in advance.
You can use the magnitude of a compute duration. Durations work for both intervals into the future and past. Adjust the start date to "snap" to the same current year so the date diff doesn't cross year boundary.
import { DateTime } from "luxon";
const startDate = DateTime.fromISO("2000-04-26").set({
year: DateTime.now().get("year")
});
const diff = Math.abs(startDate.diffNow().as('day'));
const wholeNumberedDateDifference = Math.round(diff);
if (diff <= 7) {
console.log("bday is in less than a week", wholeNumberedDateDifference);
} else {
console.log("bday is more than in a week", wholeNumberedDateDifference);
}
Output
bday is in less than a week 2
Demo

Convert the difference between 2 dates to 'y mo d' format using Moment.js

I am running into a wall trying to figure out how to convert the difference between two dates to an accurate breakdown of how many years, months and days it's been since the start date.
The format I want to show is: '1y 5mo 2d' given two dateTimes that have that difference.
I tried using Moment.js and it works pretty well for 'y' and 'mo' but I am running into a wall trying to figure out how to accurately get the number of days.
export const convertDaysToYMD = (dates: {start, end})=>{
const start = Moment(dates.start)
const end = Moment(dates.end)
const y = end.diff(start, 'years')
const m = end.diff(start, 'months')
const d = end.diff(start, 'days')
console.log('y', y + ' m', m%12 + ' d', d)
}
I can accuratly get the number of years and then the number of months by using mod(12) but due to the number of days changing per month I don't quite know how to get the number of days. Any help would be great.
You can use moment's duration method like this:
const start = moment('2020-01-02');
const end = moment('2020-02-03');
const duration = moment.duration(end.diff(start));
console.log(`${duration.years()} years ${duration.months()} months and ${duration.days()} days.`)
<script src="https://momentjs.com/downloads/moment.min.js"></script>

Age verification based on birthdate and current date

So, I need to calculate age by subtracting "todays" date from the converted date of an input field, entered by the user. Although it needs cleaned up, the below code works, I had to get creative as RN uses a different JS execution environment... see here.
My question, without adding the "+1" to this snippet "b.getMonth() + 1", the math on the date subtraction comes back 1 month off every time. When I add the "+1" it works like a charm, why? If it's a logical fix, I don't mind keeping the "+1," but I would surely like to know why the "+1" is necessary.
Also, totally open to improved solutions to this problem, keep in mind I had a much simpler function that worked great while debugger was open, once closed, it did not work, see the link above.
getVerifyBirthday(birthday) {
const b = new Date();
var verify = birthday.length;
const utc2 = Date.UTC(b.getFullYear(), b.getMonth() + 1, b.getDate());
if (verify === 10) {
const splitBirth = birthday.split('-');
var mydate = new Date(splitBirth[2], splitBirth[0], splitBirth[1]);
const a = mydate;
const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
const diffTime = Math.abs(utc2 - utc1);
const diffYears = (diffTime / (3.15576e+10));
this.setState({ diffYears: diffYears});
return diffYears >= 13;
} else {}
}
Update
I ended up refactoring my original function, leaving the (+1) on months due to months starting at 0, as mentioned below. I still had to split both dates, when I didn't split both, my age came back NaN/Undefined; not sure if this goes back to the RN execution environment vs browser, but I digress.
I'd make a few of my own suggestions over here:
there's no need to hussle with UTC dates (to make sure whether the user in his timezone has already reached the age of 13, assuming along the way that he or she was born in that same timezone ;)
there's no need to split mm-dd-yyyy date string to convert into Date, it may be parsed by new Date()
counting years as 365.25 days has certain error margin depending on the exact leap years quantity that passed since the user's birth year, instead whole years may be compared together with dates
To me, it makes more sense to decompose date strings into days, months and years and make decision based on full years difference minus 1 year (if the person didn't yet celebrate his/her birthday this year):
const today = new Date().toISOString().slice(0,10), // yyyy-mm-dd
birthday = '1982-06-21',
[bYear, bMonth, bDay] = birthday.split('-'),
[tYear, tMonth, tDay] = today.split('-'),
diffYears = tYear - bYear - (bMonth > tMonth || bDay > tDay ? 1 : 0)
console.log(diffYears)
.as-console-wrapper{min-height:100%;}
Months are zero-based in JavaScript Date objects. However, if you get a formatted string, they start from 1:
const date = new Date(2020, 1, 17); // 17th of February 2020
console.log("getMonth:", date.getMonth()); //month is 1
console.log("formatted:", date.toISOString()); //month is 2
So, actually what happens is that you're shifting both dates a month forward. This sort of works:
const originDate = new Date(2020, 1, 17); // 17th of February 2020
const originString = "2020-02-17".split("-");
const dateFromDate = new Date(originDate.getFullYear(), originDate.getMonth() + 1, originDate.getDate())
const dateFromString = new Date(originString[0], originString[1], originString[2])
console.log("dateFromDate:", dateFromDate); //month is 3
console.log("dateFromString:", dateFromString); //month is 3
When you do the subtraction it evens out but you can still run into an overflow of the date for months with different number of days:
const originDate = new Date(2020, 0, 31); // 31st of January 2020
const dateFromDate = new Date(originDate.getFullYear(), originDate.getMonth() + 1, originDate.getDate())
console.log("dateFromDate:", dateFromDate); // 1st of March 2020
This still works logically for most cases, however you are bound to run into a problem at some point if you shift months forward. So, instead you should be doing the opposite and subtracting 1 when converting a 1-based number into a Date object:
const originString = "2020-02-17".split("-");
const dateFromString = new Date(originString[0], originString[1] - 1, originString[2])
console.log("dateFromString:", dateFromString); //month is 2

Momentjs / Angularjs - Checking if 2 dates are in the same period - TimeSheet project

I am working on a simple Timesheet app, I am trying to implement an auto calculator that will sum up your hours for each day (Sunday, Monday, Tuesday, etc ...). A problem I noticed is that in some cases, users will enter activities that will be within the same date time periods.
For example:
$scope.Example = [
{Description:"Example activity",Start:"2018-06-24 8:00",End:"2018-06-24 10:00",Total:2},
{Description:"Example activity2",Start:"2018-06-24 9:00",End:"2018-06-24 10:00",Total:1},
{Description:"Example activity3",Start:"2018-06-24 10:00",End:"2018-06-24 11:00",Total:1}];
$scope.Calculate_all_entries = function(){
$scope.Total.Sunday = 0;
if($scope.Example){
angular.forEach($scope.Example, function(element){
if(moment(element.Start).format("dddd") === "Sunday"){
$scope.Total.Sunday = $scope.Total.Sunday + element.Total;
}
})
}
}
In this case the total should be 3 hours and not 4 hours as we dont charge for work within the same hours. I'm need to implement a system that would check if the dates are within the same period and provide the appropriate total.
I found this in the documentation on momentjs that seemed to be close to what i need but only takes one value:
moment('2010-10-19 11:00').isBetween('2010-10-19 10:00', '2010-10-25 00:00'); // true
Would anyone know of any other methods to check wether or not the start and end time are in the same period as other entries in the same day?
Sure, you can use momentjs's unix() function to convert those date times to an integer which then can easily be used to check whether the timestamp is in between two other timestamps.
Here is an example:
var timeToCheck = moment('2010-10-19 11:00').unix();
var startTime = moment('2010-10-19 10:00').unix();
var endTime = moment('2010-10-25 00:00').unix();
console.log(timeToCheck >= startTime && timeToCheck <= endTime); // true

Categories

Resources