简体   繁体   English

如何正确使用 intl.formatRelativeTime()

[英]How to use intl.formatRelativeTime() in the correct way

In my React app, I have to show info saying create 1 hour ago or 1 day ago and also plural as 10 minutes ago or 3 days ago.在我的 React 应用程序中,我必须显示创建 1 小时前或 1 天前的信息,以及 10 分钟前或 3 天前的复数形式。 To achieve that I'm trying to use this API FormatJS and in the specific intl.formatRelativeTime()为了实现这一点,我正在尝试使用这个 API FormatJS并在特定的intl.formatRelativeTime()

What I tried so far is something like that到目前为止我尝试的是这样的

const CreatedConsetee = ({ date }) => {
  // date = 2021-04-26T14:21:51.771Z
  const intl = useIntl();
  const parsedDate = new Date(date);

  const dateFormat = intl.formatRelativeTime(parsedDate, 'hour', {
    style: 'long',
  });

  return <>{dateFormat}</>;
};

The result is of the above is like this上面的结果是这样的

in 1,619,446,911,771 hours

Whatever is it always that big number and I have no idea how to make it right.不管是什么,它总是那么大,我不知道如何使它正确。

The expected behavior I want is that I got a message saying created 7 days ago the same if we have 1 hour 1 minute 1 day and plural forms 2 hours 2 minutes 2 days.我想要的预期行为是,如果我们有 1 小时 1 分钟 1 天和复数 forms 2 小时 2 分钟 2 天,我收到一条消息说created 7 days ago的相同。

You would have to take the current time and diff the tiem you are formatting to get the milliseconds.您必须采用当前时间并区分您正在格式化的时间以获得毫秒数。

Now, you need to figure out the closest unit to round down to and format using that unit.现在,您需要找出最接近的单位以向下舍入并使用该单位进行格式化。

Just swap Intl.RelativeTimeFormat for intl.formatRelativeTime where applicable, but the algorithm should remain the same.只需在适用的情况下将intl.formatRelativeTime换成Intl.RelativeTimeFormat ,但算法应该保持不变。

 if (Date.prototype.getUTCTime === undefined) { Date.prototype.getUTCTime = function() { return this.getTime() - (this.getTimezoneOffset() * 60000); }; } const WEEK_IN_MILLIS = 6.048e8, DAY_IN_MILLIS = 8.64e7, HOUR_IN_MILLIS = 3.6e6, MIN_IN_MILLIS = 6e4, SEC_IN_MILLIS = 1e3; // For testing only, remove the constructor argument in production. const getCurrentUTCTime = () => new Date('2021-04-26T14:21:51.771Z').getUTCTime(); const timeFromNow = (date, formatter) => { const millis = typeof date === 'string'? new Date(date).getUTCTime(): date.getUTCTime(), diff = millis - getCurrentUTCTime(); if (Math.abs(diff) > WEEK_IN_MILLIS) return formatter.format(Math.trunc(diff / WEEK_IN_MILLIS), 'week'); else if (Math.abs(diff) > DAY_IN_MILLIS) return formatter.format(Math.trunc(diff / DAY_IN_MILLIS), 'day'); else if (Math.abs(diff) > HOUR_IN_MILLIS) return formatter.format(Math.trunc((diff % DAY_IN_MILLIS) / HOUR_IN_MILLIS), 'hour'); else if (Math.abs(diff) > MIN_IN_MILLIS) return formatter.format(Math.trunc((diff % HOUR_IN_MILLIS) / MIN_IN_MILLIS), 'minute'); else return formatter.format(Math.trunc((diff % MIN_IN_MILLIS) / SEC_IN_MILLIS), 'second'); }; const dateFormat = new Intl.RelativeTimeFormat('en', { style: 'long' }); console.log(timeFromNow('2021-04-24T14:21:51.771Z', dateFormat)); console.log(timeFromNow('2021-04-25T14:21:51.771Z', dateFormat)); console.log(timeFromNow('2021-04-26T14:21:51.771Z', dateFormat)); console.log(timeFromNow('2021-04-27T14:21:51.771Z', dateFormat)); console.log(timeFromNow('2021-04-28T14:21:51.771Z', dateFormat)); console.log(timeFromNow('2021-04-29T14:21:51.771Z', dateFormat)); console.log(timeFromNow('2021-04-30T14:21:51.771Z', dateFormat)); console.log(timeFromNow('2021-05-01T14:21:51.771Z', dateFormat)); console.log(timeFromNow('2021-05-02T14:21:51.771Z', dateFormat)); console.log(timeFromNow('2021-05-03T14:21:51.771Z', dateFormat)); console.log(timeFromNow('2021-05-04T14:21:51.771Z', dateFormat));
 .as-console-wrapper { top: 0; max-height: 100%;important; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/intl-messageformat/9.0.2/intl-messageformat.min.js"></script>

Here is a version of the code above written in React:这是上面用 React 编写的代码的一个版本:

View on CodeSandboxCodeSandbox上查看

import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { IntlProvider, useIntl } from "react-intl";

const WEEK_IN_MILLIS = 6.048e8,
  DAY_IN_MILLIS = 8.64e7,
  HOUR_IN_MILLIS = 3.6e6,
  MIN_IN_MILLIS = 6e4,
  SEC_IN_MILLIS = 1e3;

const getUTCTime = (date) => date.getTime() - date.getTimezoneOffset() * 60000;

// For testing only, remove the constructor argument in production.
const getCurrentUTCTime = () => getUTCTime(new Date());

const defaultFormatOptions = {
  style: "long"
};

const timeFromNow = (date, intl, options = defaultFormatOptions) => {
  const millis =
      typeof date === "string" ? getUTCTime(new Date(date)) : getUTCTime(date),
    diff = millis - getCurrentUTCTime();
  if (Math.abs(diff) > WEEK_IN_MILLIS)
    return intl.formatRelativeTime(
      Math.trunc(diff / WEEK_IN_MILLIS),
      "week",
      options
    );
  else if (Math.abs(diff) > DAY_IN_MILLIS)
    return intl.formatRelativeTime(
      Math.trunc(diff / DAY_IN_MILLIS),
      "day",
      options
    );
  else if (Math.abs(diff) > HOUR_IN_MILLIS)
    return intl.formatRelativeTime(
      Math.trunc((diff % DAY_IN_MILLIS) / HOUR_IN_MILLIS),
      "hour",
      options
    );
  else if (Math.abs(diff) > MIN_IN_MILLIS)
    return intl.formatRelativeTime(
      Math.trunc((diff % HOUR_IN_MILLIS) / MIN_IN_MILLIS),
      "minute",
      options
    );
  else
    return intl.formatRelativeTime(
      Math.trunc((diff % MIN_IN_MILLIS) / SEC_IN_MILLIS),
      "second",
      options
    );
};

const CreatedConsetee = ({ date }) => {
  return <>{timeFromNow(date, useIntl())}</>;
};

ReactDOM.render(
  <StrictMode>
    <IntlProvider locale={navigator.language}>
      <div className="App">
        <h1>
          <CreatedConsetee date={new Date("2021-04-26T14:21:51.771Z")} />
        </h1>
      </div>
    </IntlProvider>
  </StrictMode>,
  document.getElementById("root")
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM