作者:LIN-少爷 | 来源:互联网 | 2023-08-27 16:25
这个问题根本上是前端时区和数据库时区不一致导致的,最简单的方式就是把db的链接手动设置时区,这样的话就可以解决时区问题,但是这样还有一个问题.如果用户不在你的时区登录你的系统的话,
这个问题根本上是前端时区和数据库时区不一致导致的,最简单的方式就是把db的链接手动设置时区,这样的话就可以解决时区问题,但是这样还有一个问题.如果用户不在你的时区登录你的系统的话,这样的解决方式就失效了,接下来我就会给出一个完美的答案,因为公司的db链接规定的是新加坡,而我在中国,测试必出现问题,所以想到了下面的解决方案.
Front-End 首先是前端的处理,我是用的是angular,使用的是TypeScript
private convert ( holiday: Holiday) : Holiday { holiday. fromDate = new Date ( holiday. fromDate. getTime ( ) + Math. abs ( new Date ( ) . getTimezoneOffset ( ) ) * 60 * 1000 ) ; holiday. toDate = new Date ( holiday. toDate. getTime ( ) + Math. abs ( new Date ( ) . getTimezoneOffset ( ) ) * 60 * 1000 ) ; const copy: Holiday = Object. assign ( { } , holiday) ; return copy; }
这段代码是重要的转换代码,因为从前端取到的时间都是带有时区的,这时候我们手动把这个带有时区的时间转换成UTC,也就是国际标准时间,从而消除了时区的影响,这时候只需要在call back-end api 的时候call一下这个方法
create ( holiday: Holiday) : Observable< Holiday> { const copy &#61; this . convert ( holiday) ; return this . http. post ( this . holidayAdminUrl, copy) . pipe ( map ( ( res: any ) &#61;> { const jsonResponse &#61; res. body; this . convertItemFromServer ( jsonResponse) ; return jsonResponse; } ) ) ; }
就可以了.
Back-End 其实后端的code都差不多,但是有一个问题必须要注意,使用的时间类型必须是包含时分秒的,不能是例如LocalDate这种类型,因为这种只包含日月年,这样就会导致我们前端对时区的处理完全失效了.我个人使用的是Timestamp,做逻辑处理的时候再转成Calendar来处理.
Enhance 使用 ZonedDateTime, 可以看我另外一篇blog.
前端传过来之后用 ZonedDateTime转成UTC进行存储.
Enhance2 或者后端使用Instant作为字段类型,前端传入用toJSON(),这样就不会有时区问题了
&#64;Column ( name &#61; "start_dt" ) private Instant startDt; &#64;Column ( name &#61; "end_dt" ) private Instant endDt;
protected convertDateFromClient ( record: IRecord) : IRecord { const copy: IRecord &#61; Object. assign ( { } , record, { startDt: record. startDt && record. startDt. isValid ( ) ? record. startDt. toJSON ( ) : undefined, endDt: record. endDt && record. endDt. isValid ( ) ? record. endDt. toJSON ( ) : undefined, } ) ; return copy; }
前端接收的时候用moment把Date String 转换成moment就可以了.
import * as moment from &#39;moment&#39; ; query ( req? : any ) : Observable< EntityArrayResponseType> { const options &#61; createRequestOption ( req) ; return this . http. get < IRecord[ ] > ( this . resourceUrl, { params: options, observe: &#39;response&#39; } ) . pipe ( map ( ( res: EntityArrayResponseType) &#61;> this . convertDateArrayFromServer ( res) ) ) ; } protected convertDateArrayFromServer ( res: EntityArrayResponseType) : EntityArrayResponseType { if ( res. body) { res. body. forEach ( ( record: IRecord) &#61;> { record. startDt &#61; record. startDt ? moment ( record. startDt) : undefined; record. endDt &#61; record. endDt ? moment ( record. endDt) : undefined; } ) ; } return res; }