【问题标题】:Date formatting error in Android in React nativeReact Native中Android中的日期格式错误
【发布时间】:2021-12-07 06:58:42
【问题描述】:

我正在获得像 202001 这样的价值。

我想像 January_2020 那样隐藏它。

有没有办法像这样转换?:

202001->January_2020

我尝试通过使用 Intl 来做到这一点,它在 ios 上运行良好,但在 android 上不运行。

我尝试了以下一个。

const dateToStr = (input) => {
    if (input.length !== 6) {
      return "wrong date syntax, use YYYYMM";
    }
    const parts = input.match(/([0-9]{4})([0-9]{2})/);
    if (!parts) {
      return "wrong date syntax, use YYYYMM";
    }
    // NOTE: check syntax of parts
    const formatter = new Intl.DateTimeFormat("en-EN", { month: "long" })
      .format;
    const formatted = formatter(
      new Date(Date.UTC(parseInt(parts[1]), parseInt(parts[2]) - 1))
    );

    return `${formatted}_${parts[1]}`;
  };

如何在不使用 android 和 ios 中的任何库的情况下在 Javascript 中获取此更新值?

【问题讨论】:

  • 你可以使用moment。即时刻('202001','YYYYMM').format('MMM_YYYY')。

标签: javascript reactjs react-native


【解决方案1】:

虽然您可以只创建一个解析函数,而忽略使用内置日期格式化功能或其他日期操作库(您将了解到这些库也可能无法在 Android 上运行!),但让我们来说明您为什么使用 @ 987654324@ 适用于 iOS 而不是 Android,因为这是这个问题中更有趣的部分。

为什么我不能在 Android 上使用 Intl

您的 React Native JS 代码在 javascript 引擎中执行,这在 iOS 和 Android 之间是不同的。

iOS - 使用 JavaScriptCore (JSC) 引擎,重要的是,这是 WebKit 使用的引擎,并且源自设备上 Safari 中的现有实现。

Android - 也使用 JSC,但是这不是来自操作系统提供的 Web 浏览器,而是其用于 JSC 引擎的无头版本的二进制文件作为 React Native 的 NPM 依赖项包含在内。

Hermes - 当然,iOS 和 Android 都可以设置为忽略默认值并使用 Hermes JS 引擎,在这方面它的行为与 Android 相同

Intl 是一个主要用于 UI 的规范,并在大多数现代浏览器中实现,包括 iOS Safari,这就是为什么作为 React Native 运行时的一部分执行的代码能够使用它的原因。

然而,作为一个无头 JS 引擎,Android 包含的 JSC 被剥离并缺少许多专注于 UI 的 API,因为无头 JS 引擎往往用于非 UI 目的,因此无需添加 UI 膨胀。因此它没有可用的Intl API。

当使用附加到 Android 模拟器或 Android 设备的 React Native 调试器时,这可能会特别令人困惑,因为这似乎适用于 Android!这是因为在使用调试器时,React Native 会将其 JS 运行时委托给调试器的运行时,因此实际上是在您计算机上的 Chrome 浏览器实例提供的 V8 引擎中运行您的 JS(这将有 Intl API 可用) .

那么如何在 Android 上使用缺少的国际化?

有几种方法可以做到这一点...

使用不同的 JSC 构建

您可以将 Android 配置为使用具有国际化功能的不同 JSC 版本

打开你的android/app/build.gradle,你会发现这个配置块

/**
 * The preferred build flavor of JavaScriptCore.
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US.  Note that
 * this variant is about 6MiB larger per architecture than default.
 */
def jscFlavor = 'org.webkit:android-jsc:+'

使用示例并替换 org.webkit:android-jsc-intl:+ 变体,或找到适合您需要的其他变体。

添加一个 polyfill

使用 NPM 上可用的 intl polyfill,您可以在代码中修补对 Intl API 的支持。这将始终在修补之前测试Intl API 的存在,因此也可以安全地包含在您的 iOS 代码中。

您也可以只配置您需要的语言环境包,这有助于减小您的应用程序的大小。

在您的应用入口文件中导入 polyfill 和语言环境数据将使其可在应用中的任何位置用作 Intl

npm install --save intl
// configure Intl polyfill
import 'intl';
import 'intl/locale-data/jsonp/en'; // other local data is available, import each locale that you need

由于 React Native JS 运行时的进一步限制,您可能还需要 disable regexp caching

// https://www.npmjs.com/package/intl#regexp-cache--restore
import IntlPolyfill from 'intl';
IntlPolyfill.__disableRegExpRestore();

爱马仕呢???

如果使用 Hermes,更改 JSC 风格将不起作用,因为 Hermes 将 JSC 替换为 JavaScript 运行时。然而,使用 polyfill 也适用于 Hermes 构建。

我为什么要解决这个问题?

除了像您的用例一样对日期操作有用之外,以任何形式修补 Intl API 在您的 React Native 应用程序中都是值得努力的,因为它还允许您使用国际化库的全部功能,例如as react-intl,它可以帮助你以声明的方式实现日期、时间、数字、货币、语言等的 i18n

【讨论】:

    猜你喜欢
    • 2020-04-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    相关资源
    最近更新 更多