In my React app, I have to show info saying create 1 hour ago or 1 day ago and also plural as 10 minutes ago or 3 days ago. To achieve that I'm trying to use this API FormatJS and in the specific intl.formatRelativeTime()
What I tried so far is something like that
const CreatedConsetee = ({ date }) => {
// date = 2021-04-26T14:21:51.771Z
const intl = useIntl();
const parsedDate = new Date(date);
const dateFormat = intl.formatRelativeTime(parsedDate, 'hour', {
style: 'long',
});
return <>{dateFormat}</>;
};
The result is of the above is like this
in 1,619,446,911,771 hours
Whatever is it always that big number and I have no idea how to make it right.
The expected behavior I want is that I got a message saying created 7 days ago
the same if we have 1 hour 1 minute 1 day and plural forms 2 hours 2 minutes 2 days.
You would have to take the current time and diff the tiem you are formatting to get the milliseconds.
Now, you need to figure out the closest unit to round down to and format using that unit.
Just swap Intl.RelativeTimeFormat
for intl.formatRelativeTime
where applicable, but the algorithm should remain the same.
if (Date.prototype.getUTCTime === undefined) {
Date.prototype.getUTCTime = function() {
return this.getTime() - (this.getTimezoneOffset() * 60000);
};
}
const
WEEK_IN_MILLIS = 6.048e8,
DAY_IN_MILLIS = 8.64e7,
HOUR_IN_MILLIS = 3.6e6,
MIN_IN_MILLIS = 6e4,
SEC_IN_MILLIS = 1e3;
// For testing only, remove the constructor argument in production.
const getCurrentUTCTime = () => new Date('2021-04-26T14:21:51.771Z').getUTCTime();
const timeFromNow = (date, formatter) => {
const
millis = typeof date === 'string' ? new Date(date).getUTCTime() : date.getUTCTime(),
diff = millis - getCurrentUTCTime();
if (Math.abs(diff) > WEEK_IN_MILLIS)
return formatter.format(Math.trunc(diff / WEEK_IN_MILLIS), 'week');
else if (Math.abs(diff) > DAY_IN_MILLIS)
return formatter.format(Math.trunc(diff / DAY_IN_MILLIS), 'day');
else if (Math.abs(diff) > HOUR_IN_MILLIS)
return formatter.format(Math.trunc((diff % DAY_IN_MILLIS) / HOUR_IN_MILLIS), 'hour');
else if (Math.abs(diff) > MIN_IN_MILLIS)
return formatter.format(Math.trunc((diff % HOUR_IN_MILLIS) / MIN_IN_MILLIS), 'minute');
else
return formatter.format(Math.trunc((diff % MIN_IN_MILLIS) / SEC_IN_MILLIS), 'second');
};
const dateFormat = new Intl.RelativeTimeFormat('en', { style: 'long' });
console.log(timeFromNow('2021-04-24T14:21:51.771Z', dateFormat));
console.log(timeFromNow('2021-04-25T14:21:51.771Z', dateFormat));
console.log(timeFromNow('2021-04-26T14:21:51.771Z', dateFormat));
console.log(timeFromNow('2021-04-27T14:21:51.771Z', dateFormat));
console.log(timeFromNow('2021-04-28T14:21:51.771Z', dateFormat));
console.log(timeFromNow('2021-04-29T14:21:51.771Z', dateFormat));
console.log(timeFromNow('2021-04-30T14:21:51.771Z', dateFormat));
console.log(timeFromNow('2021-05-01T14:21:51.771Z', dateFormat));
console.log(timeFromNow('2021-05-02T14:21:51.771Z', dateFormat));
console.log(timeFromNow('2021-05-03T14:21:51.771Z', dateFormat));
console.log(timeFromNow('2021-05-04T14:21:51.771Z', dateFormat));
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/intl-messageformat/9.0.2/intl-messageformat.min.js"></script>
Here is a version of the code above written in React:
View on CodeSandbox
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { IntlProvider, useIntl } from "react-intl";
const WEEK_IN_MILLIS = 6.048e8,
DAY_IN_MILLIS = 8.64e7,
HOUR_IN_MILLIS = 3.6e6,
MIN_IN_MILLIS = 6e4,
SEC_IN_MILLIS = 1e3;
const getUTCTime = (date) => date.getTime() - date.getTimezoneOffset() * 60000;
// For testing only, remove the constructor argument in production.
const getCurrentUTCTime = () => getUTCTime(new Date());
const defaultFormatOptions = {
style: "long"
};
const timeFromNow = (date, intl, options = defaultFormatOptions) => {
const millis =
typeof date === "string" ? getUTCTime(new Date(date)) : getUTCTime(date),
diff = millis - getCurrentUTCTime();
if (Math.abs(diff) > WEEK_IN_MILLIS)
return intl.formatRelativeTime(
Math.trunc(diff / WEEK_IN_MILLIS),
"week",
options
);
else if (Math.abs(diff) > DAY_IN_MILLIS)
return intl.formatRelativeTime(
Math.trunc(diff / DAY_IN_MILLIS),
"day",
options
);
else if (Math.abs(diff) > HOUR_IN_MILLIS)
return intl.formatRelativeTime(
Math.trunc((diff % DAY_IN_MILLIS) / HOUR_IN_MILLIS),
"hour",
options
);
else if (Math.abs(diff) > MIN_IN_MILLIS)
return intl.formatRelativeTime(
Math.trunc((diff % HOUR_IN_MILLIS) / MIN_IN_MILLIS),
"minute",
options
);
else
return intl.formatRelativeTime(
Math.trunc((diff % MIN_IN_MILLIS) / SEC_IN_MILLIS),
"second",
options
);
};
const CreatedConsetee = ({ date }) => {
return <>{timeFromNow(date, useIntl())}</>;
};
ReactDOM.render(
<StrictMode>
<IntlProvider locale={navigator.language}>
<div className="App">
<h1>
<CreatedConsetee date={new Date("2021-04-26T14:21:51.771Z")} />
</h1>
</div>
</IntlProvider>
</StrictMode>,
document.getElementById("root")
);