import { Tooltip } from 'antd';
import moment from 'moment';
import type { CSSProperties } from 'react';
import { useMemo } from 'react';
import { useIntl } from 'umi';
export interface TimeFromNowProps {
style?: CSSProperties;
time: number | string | Date;
format?: string;
tooltip?: boolean;
/**
* 表示时间距离限制,超出限制则以标准时间(format配置的格式)展示,例:
* ['month', 1] 表示超过两个月(包括两个月)则以标准时间展示;
* ['day', 1] 表示超过两天(包括两天)则以标准时间展示。
*/
limit?: ['year' | 'month' | 'day' | 'hour' | 'minute', number] | false;
}
const TimeFromNow = (props: TimeFromNowProps) => {
const {
style,
time,
format = 'YYYY-MM-DD HH:mm:ss',
tooltip = true,
limit = ['month', 1],
} = props;
const { formatMessage } = useIntl();
const { result, standardTime } = useMemo(() => {
const targetDate = moment(time).toDate();
const now = new Date();
const timeDiff = now.getTime() - targetDate.getTime(); // 毫秒差值
// 计算时间差值
const seconds = Math.floor(timeDiff / 1000); // 秒
const minutes = Math.floor(seconds / 60); // 分钟
const hours = Math.floor(minutes / 60); // 小时
const days = Math.floor(hours / 24); // 天
const months = Math.floor(days / 30); // 月
const years = Math.floor(months / 12); // 年
const res = {
/** 格式化时间 */
result: '',
/** 是否为标准时间格式 */
standardTime: true,
};
const fromNow = () => {
if (years > 0) {
return formatMessage({ id: 'component.TimeFromNow.year' }).replace(
'${year}',
String(years),
);
} else if (months > 0) {
return formatMessage({ id: 'component.TimeFromNow.month' }).replace(
'${month}',
String(months),
);
} else if (days > 0) {
return formatMessage({ id: 'component.TimeFromNow.day' }).replace('${day}', String(days));
} else if (hours > 0) {
return formatMessage({ id: 'component.TimeFromNow.hour' }).replace(
'${hour}',
String(hours),
);
} else if (minutes > 0) {
return formatMessage({ id: 'component.TimeFromNow.minute' }).replace(
'${minute}',
String(minutes),
);
} else {
return formatMessage({ id: 'component.TimeFromNow.just' });
}
};
if (limit === false) {
res.result = fromNow();
res.standardTime = false;
} else {
const [limitType, limitValue] = Array.isArray(limit) ? limit : ['month', 1];
if (limitType && limitValue > 0) {
const some = [
limitType === 'year' && years > limitValue,
limitType === 'month' && months > limitValue,
limitType === 'day' && days > limitValue,
limitType === 'hour' && hours > limitValue,
limitType === 'minute' && minutes > limitValue,
].some((v) => v);
if (some) {
res.result = moment(time).format(format);
} else {
res.result = fromNow();
res.standardTime = false;
}
} else {
res.result = fromNow();
res.standardTime = false;
}
}
return res;
}, [format, formatMessage, limit, time]);
return tooltip && !standardTime ? (
{result}
) : (
{result}
);
};
export default TimeFromNow;