@jsenv/humanize 1.7.0 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -993,48 +993,90 @@ const setDecimalsPrecision = (
993
993
  // return numberTruncated
994
994
  // }
995
995
 
996
- const humanizeEllapsedTime = (ms, { short } = {}) => {
996
+ const UNIT_MS = {
997
+ year: 31_557_600_000,
998
+ month: 2_629_000_000,
999
+ week: 604_800_000,
1000
+ day: 86_400_000,
1001
+ hour: 3_600_000,
1002
+ minute: 60_000,
1003
+ second: 1000,
1004
+ };
1005
+ const UNIT_KEYS = Object.keys(UNIT_MS);
1006
+ const SMALLEST_UNIT_NAME = UNIT_KEYS[UNIT_KEYS.length - 1];
1007
+ const TIME_DICTIONARY_EN = {
1008
+ year: { long: "year", plural: "years", short: "y" },
1009
+ month: { long: "month", plural: "months", short: "m" },
1010
+ week: { long: "week", plural: "weeks", short: "w" },
1011
+ day: { long: "day", plural: "days", short: "d" },
1012
+ hour: { long: "hour", plural: "hours", short: "h" },
1013
+ minute: { long: "minute", plural: "minutes", short: "m" },
1014
+ second: { long: "second", plural: "seconds", short: "s" },
1015
+ joinDuration: (primary, remaining) => `${primary} and ${remaining}`,
1016
+ };
1017
+ const TIME_DICTIONARY_FR = {
1018
+ year: { long: "an", plural: "ans", short: "a" },
1019
+ month: { long: "mois", plural: "mois", short: "m" },
1020
+ week: { long: "semaine", plural: "semaines", short: "s" },
1021
+ day: { long: "jour", plural: "jours", short: "j" },
1022
+ hour: { long: "heure", plural: "heures", short: "h" },
1023
+ minute: { long: "minute", plural: "minutes", short: "m" },
1024
+ second: { long: "seconde", plural: "secondes", short: "s" },
1025
+ joinDuration: (primary, remaining) => `${primary} et ${remaining}`,
1026
+ };
1027
+
1028
+ const humanizeEllapsedTime = (
1029
+ ms,
1030
+ {
1031
+ short,
1032
+ lang = "en",
1033
+ timeDictionnary = lang === "fr" ? TIME_DICTIONARY_FR : TIME_DICTIONARY_EN,
1034
+ } = {},
1035
+ ) => {
997
1036
  if (ms < 1000) {
998
- return short ? "0s" : "0 second";
1037
+ return short
1038
+ ? `0${timeDictionnary.second.short}`
1039
+ : `0 ${timeDictionnary.second.long}`;
999
1040
  }
1000
1041
  const { primary, remaining } = parseMs(ms);
1001
1042
  if (!remaining) {
1002
- return inspectEllapsedUnit(primary, short);
1043
+ return inspectEllapsedUnit(primary, { short, timeDictionnary });
1003
1044
  }
1004
- return `${inspectEllapsedUnit(primary, short)} and ${inspectEllapsedUnit(
1005
- remaining,
1045
+ const primaryText = inspectEllapsedUnit(primary, {
1006
1046
  short,
1007
- )}`;
1047
+ timeDictionnary,
1048
+ });
1049
+ const remainingText = inspectEllapsedUnit(remaining, {
1050
+ short,
1051
+ timeDictionnary,
1052
+ });
1053
+ return timeDictionnary.joinDuration(primaryText, remainingText);
1008
1054
  };
1009
- const inspectEllapsedUnit = (unit, short) => {
1055
+ const inspectEllapsedUnit = (unit, { short, timeDictionnary }) => {
1010
1056
  const count =
1011
1057
  unit.name === "second" ? Math.floor(unit.count) : Math.round(unit.count);
1012
- let name = unit.name;
1058
+ const name = unit.name;
1013
1059
  if (short) {
1014
- name = unitShort[name];
1015
- if (count <= 1) {
1016
- return `${count}${name}`;
1017
- }
1018
- return `${count}${name}s`;
1060
+ const unitText = timeDictionnary[name].short;
1061
+ return `${count}${unitText}`;
1019
1062
  }
1020
1063
  if (count <= 1) {
1021
- return `${count} ${name}`;
1064
+ const unitText = timeDictionnary[name].long;
1065
+ return `${count} ${unitText}`;
1022
1066
  }
1023
- return `${count} ${name}s`;
1024
- };
1025
- const unitShort = {
1026
- year: "y",
1027
- month: "m",
1028
- week: "w",
1029
- day: "d",
1030
- hour: "h",
1031
- minute: "m",
1032
- second: "s",
1067
+ const unitText = timeDictionnary[name].plural;
1068
+ return `${count} ${unitText}`;
1033
1069
  };
1034
1070
 
1035
1071
  const humanizeDuration = (
1036
1072
  ms,
1037
- { short, rounded = true, decimals } = {},
1073
+ {
1074
+ short,
1075
+ rounded = true,
1076
+ decimals,
1077
+ lang = "en",
1078
+ timeDictionnary = lang === "fr" ? TIME_DICTIONARY_FR : TIME_DICTIONARY_EN,
1079
+ } = {},
1038
1080
  ) => {
1039
1081
  // ignore ms below meaningfulMs so that:
1040
1082
  // humanizeDuration(0.5) -> "0 second"
@@ -1044,7 +1086,9 @@ const humanizeDuration = (
1044
1086
  // yes we could return "0.1 millisecond" but we choosed consistency over precision
1045
1087
  // so that the prefered unit is "second" (and does not become millisecond when ms is super small)
1046
1088
  if (ms < 1) {
1047
- return short ? "0s" : "0 second";
1089
+ return short
1090
+ ? `0${timeDictionnary.second.short}`
1091
+ : `0 ${timeDictionnary.second.long}`;
1048
1092
  }
1049
1093
  const { primary, remaining } = parseMs(ms);
1050
1094
  if (!remaining) {
@@ -1053,52 +1097,51 @@ const humanizeDuration = (
1053
1097
  decimals === undefined ? (primary.name === "second" ? 1 : 0) : decimals,
1054
1098
  short,
1055
1099
  rounded,
1100
+ timeDictionnary,
1056
1101
  });
1057
1102
  }
1058
- return `${humanizeDurationUnit(primary, {
1103
+ const primaryText = humanizeDurationUnit(primary, {
1059
1104
  decimals: decimals === undefined ? 0 : decimals,
1060
1105
  short,
1061
1106
  rounded,
1062
- })} and ${humanizeDurationUnit(remaining, {
1107
+ timeDictionnary,
1108
+ });
1109
+ const remainingText = humanizeDurationUnit(remaining, {
1063
1110
  decimals: decimals === undefined ? 0 : decimals,
1064
1111
  short,
1065
1112
  rounded,
1066
- })}`;
1113
+ timeDictionnary,
1114
+ });
1115
+ return timeDictionnary.joinDuration(primaryText, remainingText);
1067
1116
  };
1068
- const humanizeDurationUnit = (unit, { decimals, short, rounded }) => {
1117
+ const humanizeDurationUnit = (
1118
+ unit,
1119
+ { decimals, short, rounded, timeDictionnary },
1120
+ ) => {
1069
1121
  const count = rounded
1070
1122
  ? setRoundedPrecision(unit.count, { decimals })
1071
1123
  : setPrecision(unit.count, { decimals });
1072
- let name = unit.name;
1124
+ const name = unit.name;
1073
1125
  if (short) {
1074
- name = unitShort[name];
1075
- return `${count}${name}`;
1126
+ const unitText = timeDictionnary[name].short;
1127
+ return `${count}${unitText}`;
1076
1128
  }
1077
1129
  if (count <= 1) {
1078
- return `${count} ${name}`;
1130
+ const unitText = timeDictionnary[name].long;
1131
+ return `${count} ${unitText}`;
1079
1132
  }
1080
- return `${count} ${name}s`;
1081
- };
1082
- const MS_PER_UNITS = {
1083
- year: 31_557_600_000,
1084
- month: 2_629_000_000,
1085
- week: 604_800_000,
1086
- day: 86_400_000,
1087
- hour: 3_600_000,
1088
- minute: 60_000,
1089
- second: 1000,
1133
+ const unitText = timeDictionnary[name].plural;
1134
+ return `${count} ${unitText}`;
1090
1135
  };
1091
1136
 
1092
1137
  const parseMs = (ms) => {
1093
- const unitNames = Object.keys(MS_PER_UNITS);
1094
- const smallestUnitName = unitNames[unitNames.length - 1];
1095
- let firstUnitName = smallestUnitName;
1096
- let firstUnitCount = ms / MS_PER_UNITS[smallestUnitName];
1097
- const firstUnitIndex = unitNames.findIndex((unitName) => {
1098
- if (unitName === smallestUnitName) {
1138
+ let firstUnitName = SMALLEST_UNIT_NAME;
1139
+ let firstUnitCount = ms / UNIT_MS[SMALLEST_UNIT_NAME];
1140
+ const firstUnitIndex = UNIT_KEYS.findIndex((unitName) => {
1141
+ if (unitName === SMALLEST_UNIT_NAME) {
1099
1142
  return false;
1100
1143
  }
1101
- const msPerUnit = MS_PER_UNITS[unitName];
1144
+ const msPerUnit = UNIT_MS[unitName];
1102
1145
  const unitCount = Math.floor(ms / msPerUnit);
1103
1146
  if (unitCount) {
1104
1147
  firstUnitName = unitName;
@@ -1107,7 +1150,7 @@ const parseMs = (ms) => {
1107
1150
  }
1108
1151
  return false;
1109
1152
  });
1110
- if (firstUnitName === smallestUnitName) {
1153
+ if (firstUnitName === SMALLEST_UNIT_NAME) {
1111
1154
  return {
1112
1155
  primary: {
1113
1156
  name: firstUnitName,
@@ -1115,9 +1158,9 @@ const parseMs = (ms) => {
1115
1158
  },
1116
1159
  };
1117
1160
  }
1118
- const remainingMs = ms - firstUnitCount * MS_PER_UNITS[firstUnitName];
1119
- const remainingUnitName = unitNames[firstUnitIndex + 1];
1120
- const remainingUnitCount = remainingMs / MS_PER_UNITS[remainingUnitName];
1161
+ const remainingMs = ms - firstUnitCount * UNIT_MS[firstUnitName];
1162
+ const remainingUnitName = UNIT_KEYS[firstUnitIndex + 1];
1163
+ const remainingUnitCount = remainingMs / UNIT_MS[remainingUnitName];
1121
1164
  // - 1 year and 1 second is too much information
1122
1165
  // so we don't check the remaining units
1123
1166
  // - 1 year and 0.0001 week is awful