date-fns Format Date and Age calculation problem in React - javascript

I was using "moment.js" in my project (like age calculator), but I want to replace it with "date-fns".
Using moment.js, I formatted the input value as DD / MM / YYYY (for TR) and was calculating the age by subtracting the current date but right now I am having trouble doing this with date-fns. I felt like moment.js came easier to use.
Moment.js age calculator codes: I entered the input on 10/03/1998. (DD/MM/YYYY -> Turkey)
const birthDay = moment(value, 'DD/MM/YYYY');
console.log(birthDay); // (output: 10/03/1998)
const now = moment();
console.log(now); // (output: Thu Mar 04 2021 10:40:09 // TR Local Time)
const age = moment.duration(now.diff(birthDay)).years();
console.log(age); // (output: 22)
I tried to do it with date-fns but was not successful. I can not calculate the age.
const birthDay = format(new Date(value), 'dd/MM/yyyy');
console.log(birthDay); // (output: 03/10/1998 - **issue 1**)
const now = new Date();
console.log(now); // (output: Thu Mar 04 2021 10:45:18 // TR Local Time)
const age = differenceInCalendarYears(now, birthDay);
console.log(age); // (output: NaN - - **issue 2**)
I would appreciate it if you could help with date-fns.
I edited for the answer, right now it's like this:
const birthDay = new Date(value);
console.log(birthDay); // Oct 03 1998 (03/10/1998) it's MM/DD, I want DD/MM
const now = new Date();
console.log(now); // Mar 04 2021
const age = differenceInCalendarYears(now, birthDay);
console.log(age); // it should be 22 but 23.

Your age depends on whether you had your anniversary on the current year. That's why you should NOT use differenceInCalendarYears to calculate the age: it does not take into account the current month and day, only the year.
Use differenceInYears instead, or intervalToDuration if you want to get the age including months and days.
const { differenceInCalendarYears, differenceInYears, intervalToDuration, parse } = require("date-fns")
function calculateAge(dob) {
const date = parse(dob, "dd/MM/yyyy", new Date());
const age = differenceInYears(new Date(), date);
return age;
}
// INCORRECT
function calculateAge2(dob) {
const date = parse(dob, "dd/MM/yyyy", new Date());
const age = differenceInCalendarYears(new Date(), date);
return age;
}
console.log("dob = 01/04/2000"); // Running on 2021-08-05
console.log('- using differenceInYears: ', calculateAge("01/04/2000")); // 21
console.log('- using differenceInCalendarYears: ', calculateAge2("01/04/2000")); // 21
console.log("dob = 01/10/2000"); // Running on 2021-08-05
console.log('- using differenceInYears: ', calculateAge("01/10/2000")); // 20
console.log('- using differenceInCalendarYears: ', calculateAge2("01/10/2000")); // 21
function calculateFullAge(dob) {
const birthDate = parse(dob, "dd/MM/yyyy", new Date());
const { years, months, days } = intervalToDuration({ start: birthDate, end: new Date()});
return { years, months, days };
}
// Running on 2021-08-05
console.log('- using intervalToDuration: ', calculateFullAge("01/04/2000")); // {years: 21, months: 4, days: 4}
console.log('- using intervalToDuration: ', calculateFullAge("01/10/2000")); // {years: 20, months: 10, days: 4}
You can run this in the following runkit

I recently had a similar situation & this is how I implemented it
import { differenceInYears, parse } from "date-fns"
const calculateAge = (dob: string): number => {
const date = parse(dob, "dd/MM/yyyy", new Date())
const age = differenceInYears(new Date(), date)
return age
}
calculateAge("11/11/2019") // returns 2
PS: consider removing types (:string & :number) if you're only using JS

Try this ;)
import { intervalToDuration } from "date-fns"
const calculateAge = (dob: string): number => {
const interval = intervalToDuration({
start: new Date(dob),
end: new Date(),
})
return interval.years ? interval.years : 0
}

Your problem is parsing the date string (timestamp) using:
const birthDay = new Date(value);
It's strongly recommended not to use the built–in parser, see Why does Date.parse give incorrect results?
Since you're using Date.fns, use it for parsing too.
And as #volpato points out, you should use differenceInYears not differenceInCalendarYears as the later is effectively just currentDate.getFullYear() - birthday.getFullYear():
let dateFns = require("date-fns")
let d = '10/03/1998'; // 10 Mar 1998
let date = dateFns.parse(d, 'dd/MM/yyyy', new Date());
let age = dateFns.differenceInYears(new Date(), date);
console.log(age); // 23 when run on 4 Mar 2021
The above can be run at npm.runkit.com

Related

Google Apps Script: Is a date part with a range

I would like to determine what season a date falls between. The date is in a cell and is not related to the current date.
I have gotten this far:
var myDate=myForm.getRange("C4").getValue();
if (Utilities.formatDate(myDate, "GMT", 'MM/dd')>'12/21' && Utilities.formatDate(myDate, "GMT", 'MM/dd')<'3/20'){
ui.alert("Winter")
}
I would repeat this obviously for other seasons.
My expectation is that 1/13/2023 evaluates to 1/13 by (Utilities.formatDate(myDate, "GMT", 'MM/dd') and falls with the range.
That is not happening
Thanks in advance.
Here is an example of comparing today's date with the season.
function getSeason() {
try {
// per Farmers Almanac
let season = ["Winter","Spring","Summer","Fall"];
let seasons = [["12/21/2021","3/20/2022","6/21/2022","9/22/2022","12/21/2022","3/20/2023"],
["12/21/2022","3/20/2023","6/21/2023","9/23/2023","12/21/2023","3/20/2024"],
["12/21/2023","3/19/2024","6/20/2024","9/22/2024","12/21/2024","3/20/2025"],
["12/21/2024","3/20/2025","6/20/2025","9/22/2025","12/21/2025","3/20/2026"],
["12/21/2025","3/20/2026","6/21/2026","9/22/2026","12/21/2026","3/20/2027"]];
let today = new Date();
let year = today.getFullYear()-2022;
today = new Date(today.getFullYear(),today.getMonth(),today.getDate());
let found = seasons[year].findIndex( (date,index) => {
return today >= new Date(date) && today < new Date(seasons[year][index+1]);
}
);
console.log(today);
console.log(season[found])
}
catch(err) {
console.log(err);
}
}
12:20:50 PM Notice Execution started
12:20:50 PM Info Mon Sep 12 2022 00:00:00 GMT-0700 (Pacific Daylight Time)
12:20:50 PM Info Summer
12:20:50 PM Notice Execution completed
Reference
Date object
Array.findIndex()
Season of the year:
function seasonOfTheYear(date) {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const ds = sh.getDataRange().getValues();
const sObj = { pA: [] };
ds.forEach(s => {
sObj[new Date(s[1]).valueOf()] = { start: new Date(s[1]), season: s[0] };
sObj.pA.push(new Date(s[1]).valueOf());
});
let dv = new Date(date).valueOf();
let ssn = sObj.pA.reduce((a, c, i) => {
if (dv >= c && dv < sObj.pA[(i + 1) % sObj.pA.length]) {
a["season"] = sObj[c].season;
}
return a;
}, {season:''}).season;
Logger.log(ssn);
}
I got this data from timeandate.com and put it into Sheet0
A
B
SPRING
Tuesday, March 1
SUMMER
Wednesday, June 1
FALL
Thursday, September 1
WINTER
Thursday, December 1

Easy way to parse "February 03, 2022 at 04:52PM" into Date in Javascript

Apologies, I'm a noob with Javascript and I couldn't see any easy way to parse February 03, 2022 at 04:52PM into a Date object.
The best I can think of is using Regex to split each part of the string into it's own component and then create a new Date object. But I'll need a switch statement to parse the month also.
I need to do this in plain JS, no libraries.
I ended up doing this the hard way. I wish Javascript supported the C standard date and time specifiers to parse date strings, but I guess this will have to do:
jsfiddle
function getDateObj(inputStr){
const monthObj = {
'Jan':0,
'Feb':1,
'Mar':2,
'Apr':3,
'May':4,
'Jun':5,
'Jul':6,
'Aug':7,
'Sep':8,
'Oct':9,
'Nov':10,
'Dec':11,
};
const regexMonth = /(...).*/;
const regexDate = /.*?\ ([0-9]{2}).*/;
const regexYear = /([0-9]{4})/;
const regexHour = /([0-9]{2}):[0-9]{2}(AM|PM)/;
const regexMin = /[0-9]{2}:([0-9]{2})(AM|PM)/;
const regexAmpm = /[0-9]{2}:[0-9]{2}((AM|PM))/;
const month = monthObj[inputStr.match(regexMonth)[1]];
const date = parseInt(inputStr.match(regexDate)[1]);
const year = parseInt(inputStr.match(regexYear)[1]);
const hour = parseInt(inputStr.match(regexHour)[1]);
const min = parseInt(inputStr.match(regexMin)[1]);
const ampm = inputStr.match(regexAmpm);
let realHour = 0;
if (ampm[1] === 'PM') {
realHour = parseInt(hour) + 12;
} else {
realHour = parseInt(hour);
}
const dateObj = new Date(year, month, date, hour, min, 0);
return dateObj;
}
console.log(getDateObj('February 03, 2022 at 04:52PM').toString());
// "Thu Feb 03 2022 04:52:00 GMT+X (XXX Standard Time)"
Well with moment.js you can parse your string as it is and define the formatting. Head over to the librarys' page and open the dev console to play with it!
basically you do want to do this:
const date = moment('February 03, 2022 at 04:52PM', 'MMMM DD, YYYY at hh:mm A')

How do I get the days between the today's day and the last day of the month using Moment.js?

Here's the code that I have right now:
const moment = require('moment')
const m = moment
const currDay = m().format('D')
const dayOfWeek = m().format('dddd')
const daysInMonth = m().daysInMonth()
const startOfMonth = moment().startOf('month').format('YYYY-MM-DD hh:mm');
const endOfMonth = moment().endOf('month').format('YYYY-MM-DD hh:mm');
I need to create a calendar row where the first item would be the todays date, and the rest of the calendar items would be the whatever amount of days are left depending on the current month so I could render each day in between in my HTML with Vue.
Example: Wed 8, Thu 9, Fri 10 ... Fri 31.
I think the OP is tripped up on the common mistake of formatting prematurely. format is good to see an intermediate result, but doing so produces a string that's no good for additional calculation.
Try to handle date objects only. Convert to strings only when you must: (a) presenting to a human reader, or (b) serializing for storage or transmission.
Working without formatting...
const daysRemainingThisMonth = moment().endOf('month').diff(moment(), 'days');
console.log(`There are ${daysRemainingThisMonth} days remaining this month`)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
Just as a POJS equivalent, if you have a function to return the last day of the month, you can use that and just get the difference between the two dates, e.g.
function getMonthEnd(date = new Date()) {
return new Date(date.getFullYear(), date.getMonth() + 1, 0);
}
function getMonthDaysLeft(date = new Date()) {
return getMonthEnd(date).getDate() - date.getDate();
}
let d = new Date();
console.log(`There are ${getMonthDaysLeft(d)} days left in ${d.toLocaleString('en',{month:'long'})}.`);
To get a list/array of the days remaining, just loop over a date, adding 1 day at a time, and write the dates in the required format into the list:
function getMonthDaysLeftAsList(date = new Date()) {
let d = new Date(+date);
// Formatter
let f = new Intl.DateTimeFormat('en',{
day: 'numeric',
month: 'short'
});
let m = d.getMonth();
let dayList = [];
while (d.getMonth() == m) {
dayList.push(f.format(d));
d.setDate(d.getDate() + 1);
}
return dayList;
}
console.log(getMonthDaysLeftAsList());

Find first monday date of month

I have a date (usually the first day of a month but not necessary, it could be any date) and I want a new date corresponding to the first Monday of that month.
example:
findFirstMonday('1 jul 2021') -> 7 jul 2021
findFirstMonday('1 aug 2021') -> 2 aug 2021
findFirstMonday('13 aug 2021') -> 2 aug 2021
Here is my code that doesn't work:
const selectedDate = new Date();
const daysInSelectedDate = daysInMonth(selectedDate);
const lastDayPreviousMonth = addDays(selectedDate, daysInSelectedDate - selectedDate.getDate() + 1);
const firstDayPreviousMonth = removeDays(
lastDayPreviousMonth,
daysInMonth(lastDayPreviousMonth),
);
console.log('firstDayPreviousMonth: ', firstDayPreviousMonth);
let firstMonday = firstDayPreviousMonth;
while (firstDayPreviousMonth.getDay() !== 1) {
console.log('firstMonday: ', firstMonday, firstMonday.getDay());
firstMonday.setDate(firstMonday.getDate() + 1);
}
console.log('firstMonday: ', firstMonday, firstMonday.getDay());
function addDays(date, days) {
const result = new Date(date)
result.setDate(result.getDate() + days)
return result
}
function removeDays(date, days) {
const result = new Date(date)
result.setDate(result.getDate() - days)
return result
}
function daysInMonth(date) {
return new Date(date.getFullYear(), date.getMonth(), 0).getDate()
}
What am I wrong?
Thanks a lot
I came up with the following code. Some explanations about the general idea:
For a given date get the first date in the month of the given date. This is quite easy by generating a new Date object with day = 1 and the year and month of the given date.
Get the weekday of the first date.
Depending on the weekday of the first date, you must calculate which day number the first Monday has. This number is calculated by ((8 - firstWeekdayInMonth) % 7). You can easily verify yourself, that this always yields a Monday. The modulo is important for Sundays and Mondays, where you would otherwise add 8 and 7 respectively, which would not yield the first Monday anymore.
console.log(findFirstMonday('1 jul 21'))
console.log(findFirstMonday('1 aug 21'))
console.log(findFirstMonday('13 aug 21'))
function findFirstMonday(dateString) {
let targetDate = new Date(dateString);
let targetMonth = targetDate.getMonth();
let targetYear = targetDate.getFullYear();
let firstDateInMonth = new Date(targetYear, targetMonth, 1);
let firstWeekdayInMonth = firstDateInMonth.getDay();
let firstMondayDate = 1 + ((8 - firstWeekdayInMonth) % 7);
return new Date(targetYear, targetMonth, firstMondayDate).toLocaleDateString();
}
Edit:
console.log(findFirstMondayMonth('1 jul 2021').toLocaleDateString())
console.log(findFirstMondayMonth('1 aug 2021').toLocaleDateString())
console.log(findFirstMondayMonth('2 aug 2021').toLocaleDateString())
console.log(findFirstMondayMonth('13 aug 2021').toLocaleDateString())
function findFirstMonday(dateString) {
let date = new Date(dateString)
let diffDay = date.getDay() - 1
if (diffDay == -1) {
diffDay = 6
}
let mondayDate = new Date(dateString);
mondayDate.setHours(mondayDate.getHours() - diffDay*24)
return mondayDate
}
function findFirstMondayMonth(dateString) {
let date = new Date(dateString)
if (date.getMonth() == findFirstMonday(date).getMonth()) {
let dateOneWeekBefore = new Date(dateString)
dateOneWeekBefore.setHours(dateOneWeekBefore.getHours() - 24 * 7)
if (date.getMonth() == dateOneWeekBefore.getMonth()) {
return findFirstMondayMonth(dateOneWeekBefore)
} else {
return findFirstMonday(date)
}
} else {
let dateOneWeekAfter = new Date(dateString)
dateOneWeekAfter.setHours(dateOneWeekAfter.getHours() + 24 * 7)
return findFirstMonday(dateOneWeekAfter)
}
}
Sorry for the last answer, I think it was the first monday of week and I don't see Sunday.getMonth() == -1

How to construct dateTime today in TypeScript?

I am trying to get DateTime today in TypeScript, here what I do in dart. I tried this in TS let dateNow: Date = new Date(); I didn't find properties to get year, month, day.
This code is in Dart 👇 this is how I get DateTime today in dart.
void main() {
final DateTime now = DateTime.now();
final today = DateTime(now.year, now.month, now.day);
final int todaySinceEpoch = today.millisecondsSinceEpoch;
print(today);
//2021-05-14 00:00:00.000
print(todaySinceEpoch);
//1620930600000
}
Thanks to Rahul Shukla his reply helped me to find the anwer date.toLocaleDateString() returns today's date in string but I wanted to get in object also I wanted the value in milliseconds since epoch.
Here is the final solution.
this returns today date with time
let now: Date = new Date();
this returns today's date without time e.g "Sat May 15 2021"
const todayDate = now.toDateString();
finally this returns today's date in milliseconds since epoch e.g 1621017000000
const todayInMilliseconds = new Date(todayDate).getTime();
To construct Date object here what I did
const year = now.getFullYear();
const month = now.getMonth();
const day = now.getDate();
const nowDate: Date = new Date(year, month, day);
or this
const nowDate: Date = new Date(2021, 4, 15);
Month count starts from 0
Since you are using new DateTime() that's why its getMonths(),getYear(), getDate() function is not available
To Get date and time in type script you can use the below code :
> new Date().toLocaleString()
> "5/14/2021, 10:07:07 AM"
To get day, months , years,
var dt = new Date();
var month = dt.getMonth();
var year =dt.getYear();
var day= dt.getDay()
This alone should do it.
let dateNow: Date = new Date();
You can use dateNow.getMonth() to get the just the month field or use dateNow.getUTCFullYear() to get the Year field.
let date: Date = new Date();
console.log("Date = " + date);
Answer:- Date = Tue Feb 05 2019 12:05:22 GMT+0530 (IST)

Categories