* 描述问题
使用日期带时区的字段,设置默认值后,在创建数据时,使用默认值提交时报错:
* 运行环境
- NocoBase 版本: 1.4.19
- 数据库种类与版本: MySQL 8.x
- 操作系统: Windows
-浏览器及版本 Chrome
- 部署方式: 源码
- Docker 镜像版本:
- NodeJS 版本: v20.18.1
如何重现
使用日期带时区的字段,设置默认值后,在创建数据时,使用默认值提交时报错
预期行为
日期带时区的字段,可以正常使用默认值提交
截图
日志
补充说明
经过排查,在 packages/core/database/src/fields/date-field.ts 代码文件中,如果是 mysql 数据库,初始化字段时会对默认值做转换:
if (this.options.defaultValue && this.database.isMySQLCompatibleDialect()) {
if (typeof this.options.defaultValue === 'string' && isIso8601(this.options.defaultValue)) {
this.options.defaultValue = moment(this.options.defaultValue)
.utcOffset(this.resolveTimeZone())
.format('YYYY-MM-DD HH:mm:ss');
}
}
在 listmeta 接口拿到的字段信息会是不带时区的格式化时间:
使用该默认值提交时,会在 create 时走到当前文件的 setter 方法中的这段逻辑:
if (typeof value === 'string' && isValidDatetime(value)) {
const dateTimezone = this.resolveTimeZone(options?.context);
const dateString = `${value} ${dateTimezone}`;
return new Date(dateString);
}
处理 resolveTimeZone 时,从字段 options 获取到的 timezone 值为 true,返回 true 导致 dateString 为非法的时间字符串。
默认的日期带时区的 options 里 timezone 值就是 true,所以这里的逻辑应该有问题:
this.resolveTimeZone = (context) => {
// @ts-ignore
const serverTimeZone = this.database.options.rawTimezone;
if (timezone === 'server') {
return serverTimeZone;
}
if (timezone === 'client') {
return context?.timezone || serverTimeZone;
}
if (timezone) {
return timezone;
}
return serverTimeZone;
};