| 
1 | 1 | const calculateDelta = (now, date) => Math.round(Math.abs(now - date) / 1000)  | 
2 | 2 | 
 
  | 
 | 3 | +const minute = 60  | 
 | 4 | +const hour = minute * 60  | 
 | 5 | +const day = hour * 24  | 
 | 6 | +const week = day * 7  | 
 | 7 | +const month = day * 30  | 
 | 8 | +const year = day * 365  | 
 | 9 | + | 
3 | 10 | export default function relativeDateFactory (translations) {  | 
4 |  | -  return function relativeDate (date, now = new Date()) {  | 
5 |  | -    if (!(date instanceof Date)) {  | 
6 |  | -      date = new Date(date)  | 
 | 11 | +  const translate = (date, now, translatePhrase, timeValue, rawValue) => {  | 
 | 12 | +    let key  | 
 | 13 | + | 
 | 14 | +    if (translatePhrase === 'justNow') {  | 
 | 15 | +      key = translatePhrase  | 
 | 16 | +    } else if (now >= date) {  | 
 | 17 | +      key = `${translatePhrase}Ago`  | 
 | 18 | +    } else {  | 
 | 19 | +      key = `${translatePhrase}FromNow`  | 
7 | 20 |     }  | 
8 | 21 | 
 
  | 
9 |  | -    let delta = null  | 
 | 22 | +    const translation = translations[key]  | 
10 | 23 | 
 
  | 
11 |  | -    const minute = 60  | 
12 |  | -    const hour = minute * 60  | 
13 |  | -    const day = hour * 24  | 
14 |  | -    const week = day * 7  | 
15 |  | -    const month = day * 30  | 
16 |  | -    const year = day * 365  | 
17 |  | - | 
18 |  | -    delta = calculateDelta(now, date)  | 
19 |  | - | 
20 |  | -    if (delta > day && delta < week) {  | 
21 |  | -      date = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)  | 
22 |  | -      delta = calculateDelta(now, date)  | 
 | 24 | +    if (typeof translation === 'function') {  | 
 | 25 | +      return translation(timeValue, rawValue)  | 
23 | 26 |     }  | 
24 | 27 | 
 
  | 
25 |  | -    const translate = (translatePhrase, timeValue) => {  | 
26 |  | -      let key  | 
27 |  | - | 
28 |  | -      if (translatePhrase === 'justNow') {  | 
29 |  | -        key = translatePhrase  | 
30 |  | -      } else if (now >= date) {  | 
31 |  | -        key = `${translatePhrase}Ago`  | 
32 |  | -      } else {  | 
33 |  | -        key = `${translatePhrase}FromNow`  | 
34 |  | -      }  | 
 | 28 | +    return translation.replace('{{time}}', timeValue)  | 
 | 29 | +  }  | 
35 | 30 | 
 
  | 
36 |  | -      const translation = translations[key]  | 
 | 31 | +  return function relativeDate (date, now = new Date()) {  | 
 | 32 | +    if (!(date instanceof Date)) {  | 
 | 33 | +      date = new Date(date)  | 
 | 34 | +    }  | 
37 | 35 | 
 
  | 
38 |  | -      if (typeof translation === 'function') {  | 
39 |  | -        return translation(timeValue)  | 
40 |  | -      }  | 
 | 36 | +    let delta = calculateDelta(now, date)  | 
41 | 37 | 
 
  | 
42 |  | -      return translation.replace('{{time}}', timeValue)  | 
 | 38 | +    if (delta > day && delta < week) {  | 
 | 39 | +      date = new Date(  | 
 | 40 | +        date.getFullYear(),  | 
 | 41 | +        date.getMonth(),  | 
 | 42 | +        date.getDate(),  | 
 | 43 | +        0,  | 
 | 44 | +        0,  | 
 | 45 | +        0  | 
 | 46 | +      )  | 
 | 47 | +      delta = calculateDelta(now, date)  | 
43 | 48 |     }  | 
44 | 49 | 
 
  | 
45 | 50 |     switch (false) {  | 
46 | 51 |       case !(delta < 30):  | 
47 |  | -        return translate('justNow')  | 
 | 52 | +        return translate(date, now, 'justNow', delta, delta)  | 
48 | 53 | 
 
  | 
49 | 54 |       case !(delta < minute):  | 
50 |  | -        return translate('seconds', delta)  | 
 | 55 | +        return translate(date, now, 'seconds', delta, delta)  | 
51 | 56 | 
 
  | 
52 | 57 |       case !(delta < 2 * minute):  | 
53 |  | -        return translate('aMinute')  | 
 | 58 | +        return translate(date, now, 'aMinute', 1, delta)  | 
54 | 59 | 
 
  | 
55 | 60 |       case !(delta < hour):  | 
56 |  | -        return translate('minutes', Math.floor(delta / minute))  | 
 | 61 | +        return translate(  | 
 | 62 | +          date,  | 
 | 63 | +          now,  | 
 | 64 | +          'minutes',  | 
 | 65 | +          Math.floor(delta / minute),  | 
 | 66 | +          delta  | 
 | 67 | +        )  | 
57 | 68 | 
 
  | 
58 | 69 |       case Math.floor(delta / hour) !== 1:  | 
59 |  | -        return translate('anHour')  | 
 | 70 | +        return translate(  | 
 | 71 | +          date,  | 
 | 72 | +          now,  | 
 | 73 | +          'anHour',  | 
 | 74 | +          Math.floor(delta / minute),  | 
 | 75 | +          delta  | 
 | 76 | +        )  | 
60 | 77 | 
 
  | 
61 | 78 |       case !(delta < day):  | 
62 |  | -        return translate('hours', Math.floor(delta / hour))  | 
 | 79 | +        return translate(date, now, 'hours', Math.floor(delta / hour), delta)  | 
63 | 80 | 
 
  | 
64 | 81 |       case !(delta < day * 2):  | 
65 |  | -        return translate('aDay')  | 
 | 82 | +        return translate(date, now, 'aDay', 1, delta)  | 
66 | 83 | 
 
  | 
67 | 84 |       case !(delta < week):  | 
68 |  | -        return translate('days', Math.floor(delta / day))  | 
 | 85 | +        return translate(date, now, 'days', Math.floor(delta / day), delta)  | 
69 | 86 | 
 
  | 
70 | 87 |       case Math.floor(delta / week) !== 1:  | 
71 |  | -        return translate('aWeek')  | 
 | 88 | +        return translate(date, now, 'aWeek', 1, delta)  | 
72 | 89 | 
 
  | 
73 | 90 |       case !(delta < month):  | 
74 |  | -        return translate('weeks', Math.floor(delta / week))  | 
 | 91 | +        return translate(date, now, 'weeks', Math.floor(delta / week), delta)  | 
75 | 92 | 
 
  | 
76 | 93 |       case Math.floor(delta / month) !== 1:  | 
77 |  | -        return translate('aMonth')  | 
 | 94 | +        return translate(date, now, 'aMonth', 1, delta)  | 
78 | 95 | 
 
  | 
79 | 96 |       case !(delta < year):  | 
80 |  | -        return translate('months', Math.floor(delta / month))  | 
 | 97 | +        return translate(date, now, 'months', Math.floor(delta / month), delta)  | 
81 | 98 | 
 
  | 
82 | 99 |       case Math.floor(delta / year) !== 1:  | 
83 |  | -        return translate('aYear')  | 
 | 100 | +        return translate(date, now, 'aYear', 1, delta)  | 
84 | 101 | 
 
  | 
85 | 102 |       default:  | 
86 |  | -        return translate('overAYear')  | 
 | 103 | +        return translate(  | 
 | 104 | +          date,  | 
 | 105 | +          now,  | 
 | 106 | +          'overAYear',  | 
 | 107 | +          Math.floor(delta / year),  | 
 | 108 | +          delta  | 
 | 109 | +        )  | 
87 | 110 |     }  | 
88 | 111 |   }  | 
89 | 112 | }  | 
0 commit comments