A Roadmap
  • Introduction
  • Roadmap
  • Basics
    • Basic Terminal Usage
      • Shell
        • 基本
        • 变量
        • 传递参数
        • 运算符
        • 命令
        • 流程控制
        • 函数
        • 输入输出重定向
    • Character Encoding
      • 字符编码
    • Data Structures & algorithms
    • Network
      • TCP/IP
      • Http/Https
        • 浏览器缓存
        • Status Code
        • GET & POST
        • HTTPS 握手过程
        • HostOnly Cookie
      • CDN
        • CDN 工作原理
    • Version Control
      • git message format
      • git commands
    • Principles
    • Design Patterns
    • Others
      • JSON
      • 正则表达式
  • Front End
    • Web Standard
      • Html
      • CSS
        • font-face 小记
        • Grid 布局简易笔记
      • Javascript
        • Ajax
          • Fetch
          • XMLHttpRequest
        • DOM
          • Selection
          • 常用 DOM 操作
          • script 标签的几个属性
        • Ecmascript
          • this 关键字
          • Event Loop
          • 隐式转换
          • Date
        • Event
          • 模拟事件
          • Others
    • Development
      • Package Management
        • npm
      • Modulization
        • 模块化机制
        • webpack 打包解析
      • Architecture
      • Build Tools
        • 如何编写一个自定义的 eslint 规则?
      • Debug
        • 移动端调试 web
      • Pre/Post Processors
      • Test
        • Jest Snapshot 使用指南
      • Type Checkers
        • TS 中 enum 的编译结果
    • Libs & frameworks
    • Platforms
      • Browser
        • Basics
          • 从输入 URL 到页面加载完成都发生了什么事情?
          • HTML 加载的过程示意图
          • 为什么读取某些属性,也会导致回流?
          • Chrome 进程模型
        • PWA
        • Compatible
        • Cross Origin
        • Performance
          • 性能检测:performance 对象
          • 性能指标
        • Others
          • 移动端 web 开发笔记
      • Server
      • Desktop Applications
      • Mobile Applications
        • Flutter 在移动端和 Web 端的技术实现
  • Back End
    • outline
    • Languages
      • Node
        • Event Loop
        • NodeJS 中的进程与线程
        • NodeJS 中的 esModule 与 commonJS
  • Clients
    • outline
    • 安装 IPA 包
  • DevOps
    • Languages
    • OS Concepts
    • Servers & terminal
  • UI & UX
    • outline
  • Others
    • Posts
      • 使用 node 爬取数据并导出到 excel
      • antd 1.x datepicker 时区问题
      • babel-transform-runtime 踩坑记录
      • lodash 按需加载注意事项
      • 记一次项目迁移的踩坑记录
      • 时区与JS中的Date对象
      • 记一次 vue + ts 开发踩坑
    • Tools
      • 个人常用的工具分享
      • tmux 简要笔记
Powered by GitBook
On this page
  • 依赖关系
  • 代码逻辑分析
  • 核心问题
  • 解决方案
  • 深入LocaleProvider的配置

Was this helpful?

  1. Others
  2. Posts

antd 1.x datepicker 时区问题

Previous使用 node 爬取数据并导出到 excelNextbabel-transform-runtime 踩坑记录

Last updated 6 years ago

Was this helpful?

Antd(1.x stable) -

依赖关系

  • 底层引用了 (~5.6.2)

  • 中使用了wrapPicker方法和createPicker方法

    const DatePicker = wrapPicker(createPicker(RcCalendar));
    const MonthPicker = wrapPicker(createPicker(MonthCalendar), 'yyyy-MM');
  • DatePicker的Date处理函数,依赖

  • gregorian-calendar内置了和两个locale配置文件,内置的时间处理对象GregorianCalendar.

    antd全局以及各组件配置了不同的locale,分别处理不同的场景,但是DatePicker最底层是直接使用了gregorian-calendar中的配置

    /*
     * en-us locale
     * @ignore
     * @author yiminghe@gmail.com
     */
    module.exports = {
      // in minutes
      timezoneOffset: -8 * 60,
      firstDayOfWeek: 0,
      minimalDaysInFirstWeek: 1,
    };
    /*
     * zh-cn locale
     * @ignore
     * @author yiminghe@gmail.com
     */
    module.exports = {
      // in minutes
      timezoneOffset: 8 * 60,
      firstDayOfWeek: 1,
      minimalDaysInFirstWeek: 1,
    };

代码逻辑分析

  • getLocale() {
      const props = this.props;
      let locale = defaultLocale;
      const context = this.context;
      if (context.antLocale && context.antLocale.DatePicker) {
        locale = context.antLocale.DatePicker;
      }
      // 统一合并为完整的 Locale
      const result = { ...locale, ...props.locale };
      result.lang = { ...locale.lang, ...props.locale.lang };
      return result;
    }
  • createPicker将props传入的locale,传递给GregorianCalendar对象生成基本的locale信息

    const props = this.props;
    const locale = props.locale;
    // 以下两行代码
    // 给没有初始值的日期选择框提供本地化信息
    // 否则会以周日开始排
    let defaultCalendarValue = new GregorianCalendar(locale);
    defaultCalendarValue.setTime(Date.now());
  • rc-calender根据locale信息进行组件渲染

    <TheCalendar
      ...
      formatter={props.getFormatter()}
      locale={locale.lang}
      ... />

核心问题

  • 1.x 的antd datepick在使用时,不根据用户的new Date().timezoneOffset设置日期,而是根据默认的local配置进行设置。分析过程见上述“代码逻辑分析”

  • 外层的antd的LocaleProvider包装组件会修改全局的locale,因此双语切换时,会存在用户的datepicker组件时区被改写的问题

解决方案

  • wrapPicker方法中会从全局的antLocale.DatePicker locale配置,将此处的timezoneOffset覆写即可

    // wrapPicker.jsx中寻找DatePicker local而配置的判断逻辑
    if (context.antLocale && context.antLocale.DatePicker) {
      locale = context.antLocale.DatePicker;
    }

深入LocaleProvider的配置

LocaleProvider的使用

import enUS from 'antd/lib/locale-provider/en_US';

...

return <LocaleProvider locale={enUS}><App /></LocaleProvider>;

locale的配置,以en_US为例

// antd/lib/locale-provider/en_US
import DatePicker from '../date-picker/locale/en_US';
import TimePicker from '../time-picker/locale/en_US';

export default {
  ...
  DatePicker,
  TimePicker,
  ...
}; 


// date-picker/locale/en_US
import GregorianCalendarLocale from 'gregorian-calendar/lib/locale/en_US';
import CalendarLocale from 'rc-calendar/lib/locale/en_US';
import TimePickerLocale from '../../time-picker/locale/en_US';

// 统一合并为完整的 Locale
const locale = { ...GregorianCalendarLocale };
locale.lang = {
  placeholder: 'Select date',
  rangePlaceholder: ['Start date', 'End date'],
  ...CalendarLocale, // 因为这里不包含timezoneOffset,就不展示这部分的内容了
};

locale.timePickerLocale = { ...TimePickerLocale };

export default locale;

wrapPicker方法默认传递一些参数给createPicker,。同时会从antd的全局locale方法中寻找DatePicker的locale配置

DatePicker
rc-calender
封装过程
gregorian-calendar(4.1.0)
en_US
zh_CN
默认使用en_US
默认传入zh_CN