咨询了几个大牛有关.NET开发中全球化的时区显示问题,大家的意见有三个:
1、使用UTC Time记录到数据库,展示的时候根据用户所选择的时区进行转换展示
2、使用固定时区DateTime记录到数据库,展示的时候根据用户所选择的时区进行转换展示
3、记录timestamp到数据库,选择DateTime.UTCTime转为秒或毫秒级别的timestamp,展示的时候转为时间类型,并根据用户所选择的时区进行转换展示
大部分人喜欢1,其次是3,最后是2
而我今天要分享的这个Oracle数据库下的开发,有个前提就是我不能修改数据库,也不能修改写入数据库的时间是指定时区的,因为Infor LN ERP中更新此时间字段,幸运的是它本来就是UTC Time。
但是呢,我不能直接用第1条方案,因为我有些筛选条件,根据用户的日期(时间)还需要筛选数据,那么我不想:既修改展示阶段的时间时区,又修改查询时候的输入时间。
于是就有了今天的非常规方案:sessiontimezone
当我们在Oracle数据库中执行以下SQL时,可以知道数据库的时区和我当前连接的时区。
SELECT BTIMEZONE,SESSIONTIMEZONE,TZ_OFFSET(DBTIMEZONE),TZ_OFFSET(SESSIONTIMEZONE) FROM DUAL;
那么我们就可以使用:TO_NUMBER(SUBSTR(TZ_OFFSET(sessiontimezone),1,3))/24,来动态的展示当前连接所在时区的时间了
SELECT TO_CHAR(A.T$CNFT + TO_NUMBER(SUBSTR(TZ_OFFSET('" + GetUserTimeZone() + "'),1,3))/24, 'YYYY-MM-DD HH24:MI:SS') AS ConfirmedTime FROM MYTABLE A
此处的GetUserTimeZone就是根据当前用户的市区设置,读取到一个“-5:00”或”6:00″形式的TimeZone。
至于用户的时区是根据用户所属的国家来还是根据用户的个人设定,这里的逻辑可以灵活设定优先级。
虽然非常规方案可以满足需要,但是不具备普遍性,性能上也会很依赖Oracle数据的配置。
如果您碰巧也有类似的场景,不妨试试这个方案。