从DateTimePicker赋值给另一个时丢失UTC时区,如何解决?
问题描述
我有一个设置了UTC: true的DateTimePicker:
<DateTimePicker id="massStartDate" displayFormat="dd MMM yyyy, HH:mm" secondsStep="60" width="20%" minDate="{config>/minDate}" value="{path : 'config>/jobShift/massStart', type: 'sap.ui.model.type.DateTime', formatOptions: { strictParsing: true , UTC: true, pattern: 'dd MMM yyyy, HH:mm:ss' }}" placeholder="Enter Start Date..."/>
需要将这个DateTimePicker的值循环传递给其他多个同样设置了UTC: true的DateTimePicker:
<DateTimePicker minDate="{config>/minDate}" displayFormat="dd MMM yyyy, HH:mm" secondsStep="60" value="{path : 'ConstraintStartTimestamp', type: 'sap.ui.model.type.DateTime', formatOptions: { strictParsing: true , UTC: true, pattern: 'dd MMM yyyy HH:mm' }}" placeholder="Enter Start Date..."/>
但传递后,目标DateTimePicker显示的时间少了一小时。具体信息:
- 初始DateTimePicker的值:
Wed Jul 12 2023 10:27:00 GMT+0100 (British Summer Time) - 目标DateTimePicker绑定的Date对象值和上述一致,但UI实际显示为09:27(比预期时间少一小时)
赋值代码如下:
for(var i = 0; i < oItems.length; i++) { var oContext = oItems[i].getBindingContext(); dStartDate = new Date(dpStartDate.getValue()); dEndDate = new Date(dpEndDate.getValue()); this.getModel().setProperty(oContext.getPath() + "/ConstraintStartTimestamp", dStartDate); this.getModel().setProperty(oContext.getPath() + "/ConstraintFinishTimestamp", dEndDate); }
解决方案
问题根源在于dpStartDate.getValue()返回的是格式化后的本地时区字符串,用这个字符串创建Date对象时,浏览器会基于本地时区解析,再结合目标控件UTC: true的格式化规则,就会产生时区偏移导致的时间差。
以下两种方案可解决该问题:
方案1:直接获取绑定模型中的原始Date对象
优先从源控件的绑定模型取原始值,避免手动解析字符串带来的时区问题:
for(var i = 0; i < oItems.length; i++) { var oContext = oItems[i].getBindingContext(); // 直接从config模型获取源控件绑定的原始Date对象 dStartDate = this.getModel("config").getProperty("/jobShift/massStart"); dEndDate = this.getModel("config").getProperty("/jobShift/massEnd"); // 替换为你的结束日期绑定路径 this.getModel().setProperty(oContext.getPath() + "/ConstraintStartTimestamp", dStartDate); this.getModel().setProperty(oContext.getPath() + "/ConstraintFinishTimestamp", dEndDate); }
方案2:将字符串解析为UTC时间后创建Date对象
如果必须通过getValue()获取字符串,需先将其转换为UTC时间再生成Date对象:
for(var i = 0; i < oItems.length; i++) { var oContext = oItems[i].getBindingContext(); // 处理开始日期 var startStr = dpStartDate.getValue(); // 按源控件displayFormat拆分字符串:dd MMM yyyy, HH:mm const [datePart, timePart] = startStr.split(", "); const [day, month, year] = datePart.split(" "); const [hour, minute] = timePart.split(":"); // 将月份名称转为数字(Jan=0,Feb=1...) const monthNum = new Date(Date.parse(`${month} 1, 2000`)).getMonth(); // 创建UTC时间的Date对象 dStartDate = new Date(Date.UTC(year, monthNum, day, hour, minute)); // 处理结束日期(逻辑同开始日期) var endStr = dpEndDate.getValue(); const [endDatePart, endTimePart] = endStr.split(", "); const [endDay, endMonth, endYear] = endDatePart.split(" "); const [endHour, endMinute] = endTimePart.split(":"); const endMonthNum = new Date(Date.parse(`${endMonth} 1, 2000`)).getMonth(); dEndDate = new Date(Date.UTC(endYear, endMonthNum, endDay, endHour, endMinute)); this.getModel().setProperty(oContext.getPath() + "/ConstraintStartTimestamp", dStartDate); this.getModel().setProperty(oContext.getPath() + "/ConstraintFinishTimestamp", dEndDate); }
额外注意事项
- 确保源和目标控件的
formatOptions.pattern与displayFormat时区规则统一,均设置UTC: true - 尽量避免手动处理日期字符串,优先通过模型传递原始
Date对象或UTC时间戳,减少时区解析误差
内容的提问来源于stack exchange,提问作者Fishrage_
相关产品推荐
相关产品推荐

