适配仓库: https://atomgit.com/oh-flutter/timezone_provider

适配分支: feat/ohos_timezone_provider_1.1.0

一、最终效果与适配目标

日历提醒、跨国会议和服务端时间换算需要的是 Asia/ShanghaiAsia/Tokyo 这样的 IANA 时区标识,不只是当前的 UTC+8。两个地区今天偏移相同,不代表历史规则或夏令时策略永远相同。timezone_provider 1.1.0 的 Dart API 正好返回 IANA ID,但原版本在 OHOS 上没有平台实现。

我的目标很窄:保留 TimezoneProvider().getTimezone(),每次调用都读取当前系统值,不缓存、不改系统设置,也不把本地化时区名称或缩写混进返回值。

在这里插入图片描述

图 1:真机宿主读取当前 IANA 时区的页面。

验证点实测结果证据
初始读取返回 Asia/Shanghai图 1、图 6
切换系统时区大阪设置下返回 Asia/Tokyo图 6
恢复系统设置返回 Asia/Shanghai,自动时区已恢复图 6
自动化与构建7 项 Dart/Widget 测试、静态分析和 HAP 构建通过图 4、图 5
能力边界按请求读取,不主动监听变化,也不修改系统时区源码与真机流程

成果速览

项目内容
上游基线TAG v1.1.0,提交 ad53d1cea2a327b72ea8d3a0ec9477027f372e5f,BSD-3-Clause
适配分支feat/ohos_timezone_provider_1.1.0
适配 TAG尚未发布
真机受测提交9c7a14425b5814c820a12cdfa0999c6fabf7fa69
当前分支 HEAD8b6690a1821ad5adb9b84c4fe4c300d81e658040,后续仅更新验证文档
新增 OHOS 能力读取系统 IANA 时区标识
真机结论Asia/Shanghai -> Asia/Tokyo -> Asia/Shanghai 通过

二、本次环境

项目实测版本
Flutter OH3.41.10-ohos-1.0.1
Dart3.11.5
DevEco Studio26.0.0 Release
HarmonyOS SDKAPI 26,示例兼容 API 18
真机CHZ-AL00,HarmonyOS 7.0.0.105
目标库timezone_provider 1.1.0

工具链准备沿用 Flutter OH 环境搭建指南。截至 2026 年 9 月 12 日,版本号最大的标签是预览版 3.44.9+ohos-0.0.1-canary1,最新正式稳定标签仍是本文实测的 3.41.10-ohos-1.0.1

三、同步仓库与建立分支

上游标签 v1.1.0 对应提交 ad53d1cea2a327b72ea8d3a0ec9477027f372e5f,许可证为 BSD-3-Clause。适配前检查了本地清单与当日组织仓库,未发现同包名 OHOS 交付。同步到 AtomGit 后保留原有历史,并在基线提交上创建统一分支。

git clone https://atomgit.com/oh-flutter/timezone_provider.git
cd timezone_provider
git switch feat/ohos_timezone_provider_1.1.0
git remote -v

复现分支和平台骨架:

git switch -c feat/ohos_timezone_provider_1.1.0 ad53d1cea2a327b72ea8d3a0ec9477027f372e5f
flutter create --template=plugin --platforms=ohos --no-pub .

模板生成后仍需改为原通道与原插件类。图 2 汇总了实际 AtomGit origin、适配分支和 HEAD,可核对仓库来源与当前分支状态。

在这里插入图片描述

图 2:AtomGit origin、适配分支和当前 HEAD。

四、原有 Dart 层保持不变

这个库采用常见的 platform interface 结构。业务调用公共类,默认实现再通过 MethodChannel('timezone_provider') 请求 getTimezone

final timezone = await TimezoneProvider().getTimezone();
// 例如 Asia/Shanghai

返回类型是非空 String。因此原生端如果得到空字符串,不能把它当成成功返回;否则业务拿到一个形式正确、语义无效的值,很难定位问题。

五、OHOS 侧读取系统时区

pubspec.yaml 新增 TimezoneProviderPlugin 注册后,ArkTS 使用 @kit.LocalizationKit

if (call.method !== 'getTimezone') {
  result.notImplemented();
  return;
}

const timezone = i18n.getTimeZone().getID();
if (timezone.length === 0) {
  result.error(
    'TIMEZONE_UNAVAILABLE',
    'The system returned an empty timezone identifier.',
    null,
  );
  return;
}
result.success(timezone);

这里每次都重新调用系统 API,所以用户更改时区后,下一次刷新会拿到新值。插件不监听变化,监听需求由另一个 flutter_timezone_observer 库负责。两个职责拆开后,读取库保持简单,业务也能按需选择。

读取不需要新增权限。未知方法必须 notImplemented,系统异常统一返回 TIMEZONE_UNAVAILABLE,不能回退到硬编码 UTC 或设备语言,因为那会制造看起来合理的错误数据。

另外,IANA ID 应原样交给时区数据库处理。展示层可以把它翻译成“上海”或“大阪”,但不应把本地化文案重新写回业务模型;名称会随语言变化,Asia/Shanghai 这样的标识才适合持久化和传给服务端。

在这里插入图片描述

图 3:MethodChannel 请求经 i18n.getTimeZone().getID() 返回 IANA 标识。

六、交付内容

本次保留原 Dart、Android、iOS、Web 代码,补充 pubspec.yaml 的 OHOS 平台声明、HAR 入口、example/ohos/、双语 OpenHarmony 文档、Dart 通道测试、widget 测试和设备测试入口。BSD-3-Clause 许可证及上游历史未改。

示例提供刷新按钮和错误重试。因为本库不订阅事件,所以系统时区切换后要主动刷新,这也是文章必须向读者说明的行为。

七、自动化和构建

flutter pub get
flutter analyze
flutter test
cd example
flutter test
flutter build hap --debug --no-codesign

实际通过 5 项插件测试和 2 项示例 widget 测试,共 7 项;静态分析无问题,未签名 HAP 构建成功。测试覆盖通道名、方法参数、重复读取、系统错误、界面刷新与失败重试。

隔离宿主通过 AtomGit 引入代码提交 9c7a14425b5814c820a12cdfa0999c6fabf7fa69 并完成签名构建、安装与真机运行。远端后续 HEAD 8b6690a 仅更新验证文档,不应说成重新受测代码。

在这里插入图片描述

图 4:Flutter 复跑与 7 项 Dart/Widget 用例统计。

在这里插入图片描述

图 5:HAP 构建产物和真机宿主锁定的 AtomGit SHA。

八、真实切换时区验证

Demo 依赖写法如下:

dependencies:
  timezone_provider:
    git:
      url: https://atomgit.com/oh-flutter/timezone_provider.git
      ref: 9c7a14425b5814c820a12cdfa0999c6fabf7fa69

执行 flutter pub get 后,应在 pubspec.lock 中核对 resolved-ref。当前没有适配 TAG,所以业务示例固定到这次真正安装到设备的 commit。

真机初始为 Asia/Shanghai。经过用户明确授权,我在系统设置中关闭自动时区并选择大阪,重启增强宿主后读取到 Asia/Tokyo;选择大连后恢复为 Asia/Shanghai。测试还与 flutter_timezone_observer 的当前值和真实变化事件交叉核对,三处结果一致。最后恢复原时区和自动设置,并保存恢复布局。

选择城市只是系统设置界面的交互入口,插件拿到的仍是规范 IANA ID。验收不比较界面上的中文城市名,避免把本地化展示差异误判成插件错误。

这里使用的是系统设置 UI,不是伪造广播,也没有直接写系统参数。仓库内 integration 和 Hypium 测试本轮未执行,真实结果来自远程 Git 依赖的隔离宿主。

在这里插入图片描述

图 6:上海、东京与恢复上海的真机读取记录。

九、提交远端

git status --short
git add pubspec.yaml ohos example test README.OpenHarmony.md README.OpenHarmony_CN.md
git commit -m "feat: add OHOS support for timezone_provider"
git push -u origin feat/ohos_timezone_provider_1.1.0

截至 2026 年 9 月 12 日,仓库公开且默认分支为适配分支,匿名读取的 HEAD 是 8b6690a1821ad5adb9b84c4fe4c300d81e658040

十、FAQ

Q1:返回的是 UTC+8 而不是 Asia/Shanghai 吗

  • 现象: 业务希望获得可用于时区数据库的标识。
  • 原因: UTC 偏移量不足以表示完整时区规则。
  • 解决方法: 直接返回 getID() 的 IANA 标识,不做缩写转换。
  • 验证结果: 真机分别读到 Asia/ShanghaiAsia/Tokyo

Q2:修改系统时区后页面没有自动更新

  • 现象: 设置页切换后,原页面仍显示旧值。
  • 原因: timezone_provider 是按请求读取,不提供事件流。
  • 解决方法: 回到页面后重新调用 getTimezone(),或接入时区观察库。
  • 验证结果: 主动刷新和增强宿主重启后均获得当前系统值。

Q3:系统调用失败时为什么不返回 UTC

  • 现象: 调用抛出 PlatformException
  • 原因: 硬编码 UTC 会把“读取失败”伪装成真实配置。
  • 解决方法: 捕获 TIMEZONE_UNAVAILABLE 并提示重试,业务自行决定降级。
  • 验证结果: Dart 测试已覆盖错误透传。

十一、总结

timezone_provider 的 OHOS 适配只做一件事:把当前系统 IANA 时区准确送回原 Dart API。7 项自动化、HAP 构建和真实 Asia/Shanghai -> Asia/Tokyo -> Asia/Shanghai 切换完成了从代码到设备的验证。它不会修改设置,也不会主动推送变化;清楚地保留这两个边界,比多加几个看似方便的默认值更可靠。

十二、参考链接

欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐