# 多时区

FlowPortal BPM支持多时区,多时区主要应用于中国公司跨国型集团企业、外国公司在中国、未来可能开展海外业务的企业。

# 多时区的具体内容

  • 发起流程、处理任务的时间显示,不同时区显示正确的本地时间
  • 系统日志等,不同时区显示正确的本地时间
  • 流程表单上填写的时间,不同时区显示正确的本地时间
  • 微应用表单上填写的时间、列表中显示的时间
  • 系统中填写的时间,如外出设置中时间,支持多时区
  • 工作日历、定时开始节点等设置应有时区设置
  • 不宜按时区显示的时间,如生日、入职时间等日期型数据

使用者无需进行额外设置,使用者的时区以电脑时区为准进行转换,比如:同样一张表单,不同时区的人,看到的是自己时区对应的时间。

数据库存储数据的时区在appsettins.json中的Persistence: TimeZone指定

"TimeZone": "China Standard Time",

用 system-time-zones命令列出所有时区

Windows时区名和Iana(Linux用)时区名字不同,系统已做了处理,都能识别。

部署程序时可以根据自己的需要进行设置,默认是中国标准时间,如图:在Server端appseting.json文件中设置。

Image

# 开发

# 一般开发者

注意邮件中的时间格式即可

yyyy-MM-dd HH:mmzzz格式(2024-06-06 09:30+08:00)

# 应用开发者

自定义开发的应用支持多时区

应用搜索中的时间如何支持多时区

1、让控件返回带时区的时间

时间控件增加了timeZone属性,想返回带时区的时间,将timeZone属性设置为true

{

        XClass:’Ext.Date.Time’,

        timeZone:true

}

检测提交数据与服务器返回json数据时间格式是否正确

不带时区:     ShipDate: 2026-06-06T09:00:00

带时区:      ShipDate: 2026-06-06T09:00:00+08:00

带时区(也正常,但不是我们系统产生和推荐的):      ShipDate: 2026-06-06T01:00:00Z

注意:日期控件缺省false,带时间的控件缺省true

2、后台存储数据时要转化为数据库时间

用EFCore存数据,无需处理,Yiez框架已处理,会自动转化为数据库时区

用自己的sql存数据库,用TimePersistenceService的ToDbTime转化为数据库时区

timePersistenceService.ToDbTime(t1);

3、后台查询数据时要转化为数据库时间再比较

用EFCore存数据,无需处理,Yiez框架已处理,会自动转化为数据库时区

var appLogs = dbContext.AppLogs

     .Where(x => x.Day >= dayFrom && x.Day <= dayTo)

     .Where(x => x.Time >= timeFrom && x.Time < timeTo);

用自己的sql存数据库,用TimePersistenceService的ToDbTime转化为数据库时区

timeTo = timePersistenceService.ToDbTime(timeTo);

# 不要带时区的时间处理

Web端时间控件

{

        XClass:’Ext.Date.Time’,

        timeZone: false

}

后端使用EFCore,设置相应字段属性UnspecifiedTimeZone

[Column("birthday")]

 [UnspecifiedTimeZone]

 public DateTime? Birthday { get; set; }

后端使用自己代码操作数据库,则无需转换时间

注意:

如果数据通过Grpc传输,不带时区的时间不能使用google.protobuf.Timestamp, Timestamp传递时间将失去时间的非特定时区属性,导致传到后台时间变成了带时区的时间而错误,建议使用ISO8601格式字符串传时间,对应的API为 DateTime. ToISO8601String和String. ISO8601ToDateTime

# 时间数据格式

Js – 带时区

mydate.timeZone = true

Json ISO8601

2024-06-06T09:00:00  (非特定时区)

2024-06-06T09:00:00+08:00 (时间和时区)

2024-06-06T09:00:00Z (utc时间)

.Net c#

myDate.Kind == DateTimeKind.Local

myDate.Kind == DateTimeKind.Unspecified

myDate.Kind == DateTimeKind.Utc

Grpc传输时间

Timestamp 传输UTC时间,用秒和纳秒记录,无法传输C#中Unspecified时间

ISO8601字符串,可以转递任何类型的C#时间

数据库时间

不带时区,存储和查询时需先将时间转化为数据库时区再做存储和查询

# 时间格式转换前台到后台

Js -> Json

mydate.timeZone == true   => 2024-06-06T09:00:00+08:00

mydate.timeZone == false   => 2024-06-06T09:00:00

Json -> C#

2024-06-06T09:00:00+08:00 => DateTimeKind.Local

2024-06-06T09:00:00 => DateTimeKind.Unspecified

C# -> Grpc

DateTimeKind.Local => Timestamp(utc)

DateTimeKind.Unspecified => ISO8601字符串

Grpc -> C#

Timestamp(utc) => DateTimeKind.Local 

ISO8601字符串 => DateTimeKind.Unspecified

C# -> 数据库时间

DateTimeKind.Local  2024-06-06 09:00:00+08:00 => 转为数据库存储时间 2024-06-06 08:00:00(西伯利亚时间)

DateTimeKind. Unspecified  2024-06-06 09:00:00 => 不转换 2024-06-06 09:00:00(西伯利亚时间)

# 时间格式转换后台到前台

数据库 -> C#

Unspecified 转时区=> DateTimeKind.Local

Unspecified 不转时区=> DateTimeKind.Unspecified 

C# -> Grpc

DateTimeKind.Local => Timestamp(utc)

DateTimeKind.Unspecified => ISO8601字符串

Grpc -> C#

Timestamp(utc) => DateTimeKind.Local  (我们的系统里面转化为Local也缺省转utc)

ISO8601字符串 => DateTimeKind.Unspecified

C# -> Json

DateTimeKind.Local => 2024-06-06T09:00:00+08:00

DateTimeKind.Unspecified  => 2024-06-06T09:00:00

Json -> JS

2024-06-06T09:00:00+08:00 => 转为用户本地时间 2024-06-06T10:00:00+09:00(东京时间)

2024-06-06T09:00:00 => 原封不动变为用户本地时间 2024-06-06T09:00:00+09:00