Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
relative-time-format
Advanced tools
The 'relative-time-format' npm package is used to format dates and times relative to the current date and time. It provides a way to display time differences in a human-readable format, such as '2 days ago' or 'in 3 hours'. This is particularly useful for applications that need to display time-related information in a user-friendly manner.
Basic Relative Time Formatting
This feature allows you to format a time difference in a human-readable way. The example shows how to format '1 day ago' and 'in 2 days' using the 'relative-time-format' package.
const RelativeTimeFormat = require('relative-time-format');
const rtf = new RelativeTimeFormat('en', { numeric: 'auto' });
console.log(rtf.format(-1, 'day')); // 'yesterday'
console.log(rtf.format(2, 'day')); // 'in 2 days'
Customizing Locale
This feature allows you to customize the locale for the relative time format. The example shows how to format the time difference in French.
const RelativeTimeFormat = require('relative-time-format');
const rtf = new RelativeTimeFormat('fr', { numeric: 'auto' });
console.log(rtf.format(-1, 'day')); // 'hier'
console.log(rtf.format(2, 'day')); // 'dans 2 jours'
Using Different Units
This feature allows you to use different units such as 'hour' and 'minute' for formatting the time difference. The example shows how to format 'an hour ago' and 'in 3 minutes'.
const RelativeTimeFormat = require('relative-time-format');
const rtf = new RelativeTimeFormat('en', { numeric: 'auto' });
console.log(rtf.format(-1, 'hour')); // 'an hour ago'
console.log(rtf.format(3, 'minute')); // 'in 3 minutes'
The 'date-fns' package provides a wide range of date utility functions, including relative time formatting. It is more comprehensive than 'relative-time-format' as it offers many other date manipulation and formatting functions.
The 'moment' package is a popular library for parsing, validating, manipulating, and formatting dates. It includes relative time formatting capabilities similar to 'relative-time-format', but it is a larger library with more features.
The 'timeago.js' package is a lightweight library specifically designed for relative time formatting. It is similar to 'relative-time-format' but focuses solely on relative time, making it a smaller and more specialized library.
This library consists of three parts:
A convenient Intl.RelativeTimeFormat
polyfill. No dependencies (doesn't require Intl.PluralRules
because it's already built in).
A high-level relative time formatting library.
A React component for relative time formatting.
npm install relative-time-format --save
If you're not using a bundler then use a standalone version from a CDN.
import RelativeTimeFormat from "relative-time-format"
import en from "relative-time-format/locale/en"
RelativeTimeFormat.addLocale(en)
// Returns "2 days ago"
new RelativeTimeFormat("en", {
style: "long" // "long" is the default. Other options: "short", "narrow".
}).format(-2, "day")
The localization resides in the locale
folder. The format of a localization is:
{
…
"day": {
"past": {
"one": "{0} day ago",
"other": "{0} days ago"
},
"future": {
"one": "in {0} day",
"other": "in {0} days"
}
},
…
}
The past
and future
can be defined by any of: zero
, one
, two
, few
, many
and other
. For more info on which is which read the official Unicode CLDR documentation. Unicode CLDR (Common Locale Data Repository) is an industry standard and is basically a collection of formatting rules for all locales (date, time, currency, measurement units, numbers, etc). All localizations come from cldr-dates-full
package (for example, en-US
).
To determine whether a certain amount of time (number) is one
, few
, or something else, relative-time-format
uses Unicode CLDR rules for formatting plurals. These rules are number quantifying functions (one for each locale) which can tell if a number should be treated as zero
, one
, two
, few
, many
or other
. Knowing how these pluralization rules work is not required but anyway here are some links for curious advanced readers: rules explanation, list of rules for all locales, list of rules for all locales in JSON format (part of cldr-core/supplemental
package), converting those rules to javascript functions. These quantifying functions can be found as quantify
properties of a locale data.
The locale
folder is generated from CLDR data by running:
npm run generate-locales
Locale data is extracted from cldr-core
(quantifiers) and cldr-dates-full
(relative time messages) packages which usually get some updates once or twice a year.
npm run update-locales
Intl.RelativeTimeFormat
is intentionally a low-level API. Third-party libraries are supposed to be built on top of this base-level API. An example of such library is javascript-time-ago
which uses Intl.RelativeTimeFormat
internally and provides a higher-level API:
import TimeAgo from 'javascript-time-ago'
// Load locale-specific relative date/time formatting rules.
import en from 'javascript-time-ago/locale/en'
// Add locale-specific relative date/time formatting rules.
TimeAgo.addLocale(en)
// Create relative date/time formatter.
const timeAgo = new TimeAgo('en-US')
timeAgo.format(new Date())
// "just now"
timeAgo.format(Date.now() - 60 * 1000)
// "a minute ago"
timeAgo.format(Date.now() - 2 * 60 * 60 * 1000)
// "2 hours ago"
timeAgo.format(Date.now() - 24 * 60 * 60 * 1000)
// "a day ago"
One can use any npm CDN service, e.g. unpkg.com or jsdelivr.net
<script src="https://unpkg.com/relative-time-format@[version]/bundle/polyfill.js"></script>
<script>
var en = ... // Somehow import `relative-time-format/locale/en`.
RelativeTimeFormat.addLocale(en)
console.log(new RelativeTimeFormat('en').format(-1, 'days'))
</script>
where [version]
is an npm package version range (for example, 0.2.x
or ^0.2.0
).
There's a test suite of about 150 test cases for Intl.RelativeTimeFormat
specification implementations. It's called "Test262". These tests check every possible imaginable aspect of formal correctness of a spec implementation including the weirdest artificial cases imaginable like accepting strings instead of numbers, accepting objects having keys 0
, 1
, etc instead of arrays, accepting objects with toString()
method instead of strings, defining all class methods as special "non-enumerable" properties via Object.defineProperty()
instead of the regular way everyone defines class methods in real life, and so on. Handling all these formal edge cases would result in an unnecessarily convoluted and less readable code and I'd prefer to keep things simple and elegant, so this library intentionally chose not to pass all of the "Test262" test cases while still passing most of them: it passes the functional correctness part and skips the not-relevant-in-real-life cases part.
This component comes with a 100% code coverage.
To run tests:
npm test
To generate a code coverage report:
npm run test-coverage
The code coverage report can be viewed by opening ./coverage/lcov-report/index.html
.
The handlebars@4.5.3
workaround in devDependencies
is for the test coverage to not produce empty reports:
Handlebars: Access has been denied to resolve the property "statements" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
This library comes with TypeScript "typings". If you happen to find any bugs in those, create an issue.
FAQs
A convenient Intl.RelativeTimeFormat polyfill
We found that relative-time-format demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.