EvanHahn / HumanizeDuration.js

361000 becomes "6 minutes, 1 second"
https://evanhahn.github.io/HumanizeDuration.js/
The Unlicense
1.65k stars 175 forks source link

Better customization control #218

Closed Sagie501 closed 10 months ago

Sagie501 commented 10 months ago

Hi!

I am using this package and I there something that I want to achieve but I can't do that with the current API that this library expose.

In my language (Hebrew) sometimes we might want to say: "Day" instead of "1 Day" / "Month" instead of "1 month" etc (in Hebrew it is "יום" instead of "1 יום").

So unfortunately with the current implementation I can't achieve it.

I don't really know what will be the best API for that but maybe with the languages property we can add this feature.

Maybe something like this:

const shortEnglishHumanizer = humanizeDuration.humanizer({
  language: "myCustomLang",
  languages: {
    myCustomLang: {
      yFormat: (num) => num === 1 ? "year" : `${num} years`,
      moFormat: (num) => num === 1 ? "month" : `${num} months`,
      wFormat: (num) => num === 1 ? "week" : `${num} weeks`,
      dFormat: (num) => num === 1 ? "day" : `${num} days`,
      ...
    },
  },
});

In that way I have much more control on what the library will return to me (of course it is just a proposal and might be a bad one but this is the idea).

Thanks!

EvanHahn commented 10 months ago

Good question.

This library is in maintenance mode so I don't intend to add new features. Three workarounds come to mind:

I'm not sure if any of these are good for you, though.

I don't know anything about Hebrew. Is the Hebrew output wrong for all users, or is it stylistic?

Sagie501 commented 10 months ago

Well, I in Hebrew it will be more common to now write the number if it is 1, but think it is still valid.

I checked the alternatives you suggested and humanize-duration seems to be a better fit to my use cases.

However, I did adopt your second suggestion, using a regular expression.

This is my code if someone will interested in similar behavior:

 import * as originalHumanizeDuration from 'humanize-duration';

export const humanizeDuration = (...args: Parameters<typeof originalHumanizeDuration>) => {
  const language = args[1]?.language;
  if (language === 'he') {
    return transformHebrewDuration(originalHumanizeDuration(...args));
  }
  return originalHumanizeDuration(...args);
};

function transformHebrewDuration(humanizeDurationOutput: string) {
  const pattern = /\b1 (\p{L}+)(,|$)/gu;
  return humanizeDurationOutput.replace(pattern, '$1$2');
}

Not the best solution in my opinion, but it currently works fine for me. I also added an eslint rule to restrict the import from the humanize-duration library.

Thanks! @EvanHahn

EvanHahn commented 10 months ago

Glad this worked for you!

Given that this seems more like a feature request than a Hebrew bug, I'm going to close. Please let me know if that's a problem.