字段实战指南:从字段配置到时区存储机制全解析)
NocoBase 日期时间含时区字段实战指南从字段配置到时区存储机制全解析【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase本文以 NocoBase 数据建模中的「日期时间含时区」Date time with timezone字段为主体完整讲解其创建配置、可编辑项、删除影响与页面/工作流用法并结合开源仓库中字段类与界面接口的源码实现深入剖析时区解析、默认值写入、X-Timezone请求头转换与输出格式化等底层机制帮助你在跨时区协作、国际化业务中正确建模时间字段。一、介绍与选型它和「日期」「时间」有什么区别在 NocoBase 中日期时间含时区用于保存日期和时间并按时区语义处理。它适合跨时区协作、国际化业务或需要明确时间点的场景比如创建预约、截止时间、执行时间。选型时的核心判断依据是「时区语义」需要时区转换、多方处于不同时区 → 选日期时间含时区本文主角只关心本地时间文本、不需要时区转换 → 选 日期时间不含时区只需要日期到日粒度→ 选 日期只需要时间 → 选 时间。从源码结构看仓库中这三类字段分别由独立类实现datetime-tz-field.ts 中的DatetimeTzField继承自 date-field.ts 的DateField类型标识为datetimeTz而不含时区与仅日期则分别由datetime-no-tz-field.ts和date-only-field.ts实现。这种继承关系意味着「含时区」字段在存储层复用了DateField的全部时区感知逻辑这也是它「按时区语义处理」的实现基础。二、适用场景日期时间含时区适合这些业务场景会议开始时间、预约时间任务截止时间、执行时间跨时区业务时间点工作流定时条件相关时间这些场景的共性是同一个时间点对不同时区的用户应呈现不同的本地时间且后端需要有一个与显示无关的绝对时间基准。下文第五节会说明 NocoBase 是如何用「数据库存储 请求头时区 输出格式化」三层结构满足这一需求的。三、创建字段配置项逐一说明在数据表的「Configure fields」页面中点击「Add field」选择「日期时间含时区」即可创建该类型字段。各配置项说明如下配置说明Field interface字段的界面类型。日期时间含时区对应datetime决定页面中如何录入和展示。Field display name字段在界面中显示的名称比如「开始时间」「截止时间」「执行时间」。建议使用业务人员能直接理解的名称。Field name字段标识名称用于 API、关系字段、权限、工作流等内部引用。创建后通常不再修改只支持字母、数字和下划线并且必须以字母开头。Field type字段在数据层的类型。日期时间含时区通常使用date。Default value默认值。新增记录时如果用户没有填写可以自动带出默认值。Validation rules校验规则。可以配置必填、时间范围等。Description字段说明。适合写字段含义、填写要求、数据来源或维护人。注意字段名创建后会被页面区块、权限、工作流和 API 引用。创建前先确认命名避免后续修改带来配置调整成本。其中「Default value」一项值得结合源码看深一层。date-field.ts 的init()中注册了beforeSave钩子它支持两个字段级选项defaultToCurrentTime新记录且该字段为空时自动写入new Date()作为默认值——即「新增时默认为当前时间」这类能力就是在这里生效的onUpdateToCurrentTime每次保存时把该字段更新为当前时间——用于「最后处理时间」一类场景。同一函数还处理了 MySQL 兼容方言下的默认值若默认值是 ISO 8601 字符串形如2024-05-12T10:30:00.000Z会先按解析出的时区偏移用 moment 格式化为YYYY-MM-DD HH:mm:ss再交给数据库保证默认值在不同时区服务器下语义一致。四、字段特性总览日期时间含时区字段的默认行为如下特性说明默认 Field interfacedatetime。默认 Field typedate。可选 Field typedate。页面组件编辑模式使用日期时间选择器。筛选支持按时间点、区间、为空、不为空筛选。排序支持按时间排序。校验支持必填和时间范围等校验。这些特性背后的实现证据分散在两个位置存储类型date-field.ts 中DateField.dataType返回 Sequelize 的DataTypes.DATE(3)即以带毫秒精度的数据库DATE类型落库。仓库为「含时区」场景准备了专门的操作符测试 datetime-tz.test.ts 验证时间点、区间等比较语义。界面接口datetime界面由 datetime-interface.ts 中的DatetimeInterface实现负责值的双向转换详见第六节并有 datetime-interface.test.ts 覆盖其行为字段类的行为则由 datetime-tz.test.ts 验证。五、时区机制纵深解析server / client / 显式时区三级解析这是「含时区」字段区别于普通日期字段的本质。从源码看NocoBase 的时区解析分为写入侧与输出侧两条链路5.1 写入侧字段级时区解析date-field.ts 中resolveTimeZone(context)的优先级为字段配置timezone: server→ 使用数据库配置中的rawTimezone服务器时区timezone: client→ 优先取请求上下文携带的时区context.timezone没有则回退服务器时区显式指定了具体时区字符串 → 直接使用未指定 → 默认服务器时区。写入链路的具体转换发生在setterL90-L105当传入值是YYYY-MM-DD HH:mm:ss格式的裸字符串正则/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/校验时会按解析出的时区拼成value 时区偏移再构造Date对象入库Date对象则原样透传。读取侧additionalSequelizeOptions()返回的get()L107-L128做对称处理从库里读到的裸时间字符串会补上服务器时区偏移后还原为Date。5.2 输出侧X-Timezone 请求头驱动格式化真正让「含时区」字段在不同客户端显示不同本地时间的是 datetime-interface.ts 中的resolveTimeZoneFromCtx(ctx)它依次尝试从 Koa 的ctx.get(X-Timezone)、ctx.request.get、各级 headers 中读取X-Timezone/x-timezone请求头返回时区偏移字符串如08:00。DatetimeInterface.toString()L204-L210在输出时将该偏移传给str2moment再按字段的x-component-props中配置的格式getDefaultFormat提供默认值完成格式化。也就是说前端在 API 请求中带上自己的时区头后端就把同一份存储值渲染成请求方时区下的本地时间——这正是「跨时区业务时间点」场景的落地方式。5.3 入参侧多种来源的宽容解析DatetimeInterface.toValue()L171-L202对写入值做了宽容处理可推断其覆盖了 API 直连与导入两类通道数字形式的日期如 Excel 导出的序列值经excelSerialToISO结合请求时区转为 ISO 字符串形如YYYY-MM-DD的纯日期、YYYYMMDD HH:mm:ss的紧凑日期时间经parseDateString拆解后由toISOWithTimezone按偏移量换算为 UTC ISO 时间L78-L107dayjs/Date/ 普通字符串原样保留无法识别的值抛出Invalid date错误。getTimeZoneOffsetMinutesL25-L51则定义了偏移字符串的合法格式数字、Z/UTC、或±HH[:MM]形式为理解哪些时区头写法有效提供了明确依据。六、编辑配置创建后点击字段右侧的「Edit」可以编辑日期时间含时区字段配置。编辑字段主要用于调整字段在 NocoBase 中的展示和使用方式比如修改显示名称、说明、默认值、校验规则或字段专属配置。如果字段来自主数据库中已经同步的表编辑时通常是在做字段映射——把数据库字段映射为 NocoBase 的 Field type 和 Field interface。配置允许编辑说明Field display name是修改字段在界面中的显示名称不改变字段标识名称。Field name否字段标识名称创建后通常不能在编辑表单中修改。Field interface条件支持主数据库字段或同步字段在字段映射时可以调整。调整后会影响页面输入、展示和校验方式。Field type条件支持主数据库字段或同步字段在字段映射时可以调整。调整前需要确认已有数据能否按新类型使用。Default value是调整新增记录时的默认值。Validation rules是调整字段校验规则。Description是补充字段含义、填写要求、数据来源或维护人。注意切换 Field type 或 Field interface 不等于简单改一个显示名称。它会影响字段的存储方式、输入组件、校验规则、筛选条件和工作流变量使用方式。已有数据较多时先确认数据格式是否匹配。这个警告在源码层面有直接对应DateField.bind()L130-L151会把 interface 为createdAt/updatedAt的字段挂接到 Sequelize 模型的_timestampAttributes并在beforeSave/beforeBulkCreate上绑定时间戳钩子。也就是说界面类型一变时间戳自动写入、保存钩子等运行时行为都会随之改变——这正是「不是改个显示名称那么简单」的技术含义。七、删除字段点击字段右侧的「Delete」可以删除日期时间含时区字段。主数据库中还可以勾选多个字段后批量删除。删除主数据库中新建的日期时间含时区字段时通常会同时删除数据库中的真实列及该列已有数据删除从数据库同步或外部数据源映射出的字段时影响范围取决于对应数据源和字段来源。警告删除字段可能影响页面区块、表单、筛选、权限、工作流、API、导入导出和已有数据。删除前先确认字段是否仍被业务配置引用。由于该字段在数据层是真实列DataTypes.DATE(3)对新建列而言删除即物理删列不可恢复对同步映射字段删除的只是 NocoBase 侧的映射关系。八、页面配置使用日期时间含时区字段适合在日历、表格、筛选和工作流中使用场景用途表单区块选择日期和时间。表格区块展示、排序和筛选时间。日历区块作为开始时间或结束时间字段。工作流作为时间条件或定时相关字段。日历、表格、工作流等场景分别由插件承接如 plugin-calendar字段侧要满足的要求是值必须是带时区语义的绝对时间、输出可按请求方时区格式化、比较操作要支持时间点与区间——前三条在本文第五节描述的存储与转换链路中已经闭环区间比较则由 operator/date 目录下的datetime-tz系列测试验证。九、相关链接字段 — 了解字段的作用、分类和映射逻辑普通表 — 在普通表中创建和管理字段日期时间不含时区 — 保存不做时区转换的日期时间日期 — 只保存日期时间 — 只保存时间【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考