]>
cat aescling's git repositories - mastodon.git/blob - app/javascript/flavours/glitch/components/relative_timestamp.js
1 import React
from 'react';
2 import { injectIntl
, defineMessages
} from 'react-intl';
3 import PropTypes
from 'prop-types';
5 const messages
= defineMessages({
6 just_now: { id: 'relative_time.just_now', defaultMessage: 'now' },
7 seconds: { id: 'relative_time.seconds', defaultMessage: '{number}s' },
8 minutes: { id: 'relative_time.minutes', defaultMessage: '{number}m' },
9 hours: { id: 'relative_time.hours', defaultMessage: '{number}h' },
10 days: { id: 'relative_time.days', defaultMessage: '{number}d' },
13 const dateFormatOptions
= {
22 const shortDateFormatOptions
= {
28 const MINUTE
= 1000 * 60;
29 const HOUR
= 1000 * 60 * 60;
30 const DAY
= 1000 * 60 * 60 * 24;
32 const MAX_DELAY
= 2147483647;
34 const selectUnits
= delta
=> {
35 const absDelta
= Math
.abs(delta
);
37 if (absDelta
< MINUTE
) {
39 } else if (absDelta
< HOUR
) {
41 } else if (absDelta
< DAY
) {
48 const getUnitDelay
= units
=> {
63 export const timeAgoString
= (intl
, date
, now
, year
) => {
64 const delta
= now
- date
.getTime();
68 if (delta
< 10 * SECOND
) {
69 relativeTime
= intl
.formatMessage(messages
.just_now
);
70 } else if (delta
< 7 * DAY
) {
72 relativeTime
= intl
.formatMessage(messages
.seconds
, { number: Math
.floor(delta
/ SECOND
) });
73 } else if (delta
< HOUR
) {
74 relativeTime
= intl
.formatMessage(messages
.minutes
, { number: Math
.floor(delta
/ MINUTE
) });
75 } else if (delta
< DAY
) {
76 relativeTime
= intl
.formatMessage(messages
.hours
, { number: Math
.floor(delta
/ HOUR
) });
78 relativeTime
= intl
.formatMessage(messages
.days
, { number: Math
.floor(delta
/ DAY
) });
80 } else if (date
.getFullYear() === year
) {
81 relativeTime
= intl
.formatDate(date
, shortDateFormatOptions
);
83 relativeTime
= intl
.formatDate(date
, { ...shortDateFormatOptions
, year: 'numeric' });
90 export default class RelativeTimestamp
extends React
.Component
{
93 intl: PropTypes
.object
.isRequired
,
94 timestamp: PropTypes
.string
.isRequired
,
95 year: PropTypes
.number
.isRequired
,
99 now: this.props
.intl
.now(),
102 static defaultProps
= {
103 year: (new Date()).getFullYear(),
106 shouldComponentUpdate (nextProps
, nextState
) {
107 // As of right now the locale doesn't change without a new page load,
108 // but we might as well check in case that ever changes.
109 return this.props
.timestamp
!== nextProps
.timestamp
||
110 this.props
.intl
.locale
!== nextProps
.intl
.locale
||
111 this.state
.now
!== nextState
.now
;
114 componentWillReceiveProps (nextProps
) {
115 if (this.props
.timestamp
!== nextProps
.timestamp
) {
116 this.setState({ now: this.props
.intl
.now() });
120 componentDidMount () {
121 this._scheduleNextUpdate(this.props
, this.state
);
124 componentWillUpdate (nextProps
, nextState
) {
125 this._scheduleNextUpdate(nextProps
, nextState
);
128 componentWillUnmount () {
129 clearTimeout(this._timer
);
132 _scheduleNextUpdate (props
, state
) {
133 clearTimeout(this._timer
);
135 const { timestamp
} = props
;
136 const delta
= (new Date(timestamp
)).getTime() - state
.now
;
137 const unitDelay
= getUnitDelay(selectUnits(delta
));
138 const unitRemainder
= Math
.abs(delta
% unitDelay
);
139 const updateInterval
= 1000 * 10;
140 const delay
= delta
< 0 ? Math
.max(updateInterval
, unitDelay
- unitRemainder
) : Math
.max(updateInterval
, unitRemainder
);
142 this._timer
= setTimeout(() => {
143 this.setState({ now: this.props
.intl
.now() });
148 const { timestamp
, intl
, year
} = this.props
;
150 const date
= new Date(timestamp
);
151 const relativeTime
= timeAgoString(intl
, date
, this.state
.now
, year
);
154 <time dateTime
={timestamp
} title
={intl
.formatDate(date
, dateFormatOptions
)}>
This page took 0.09811 seconds and 4 git commands to generate.