输入31日时dt_ini_vigencia等日期字段自动变为1日求助
问题描述
当输入框选择31日时,JSON字段dt_ini_vigencia和dt_fin_vigencia会被错误转换为当月1日。例如输入2022-12-31T03:00:00.000Z,经以下TypeScript代码处理后,dt_ini_vigencia变成2022-12-01T03:00:00.000Z,dt_fin_vigencia变成2023-12-01T03:00:00.000Z,仅31日触发该问题:
var cotacaoJson = JSON.parse(resp[0].ds_cotacao_json); var date = new Date(); date.setDate(cotacaoJson.dt_ini_vigencia.substring(8, 10)); // 问题根源所在行 date.setMonth(cotacaoJson.dt_ini_vigencia.substring(5, 7) - 1); date.setFullYear(cotacaoJson.dt_ini_vigencia.substring(0, 4)); date.setHours(0); date.setMinutes(0); date.setSeconds(0); date.setMilliseconds(0); var dateF = new Date(); dateF.setDate(cotacaoJson.dt_fin_vigencia.substring(8, 10)); dateF.setMonth(cotacaoJson.dt_fin_vigencia.substring(5, 7) - 1); dateF.setFullYear(cotacaoJson.dt_fin_vigencia.substring(0, 4)); dateF.setHours(0); dateF.setMinutes(0); dateF.setSeconds(0); dateF.setMilliseconds(0); this.cotacao = cotacaoJson; if (!this.editar) { this.cotacao.clausulas_particulares = 'N/A'; } this.cotacao.dt_ini_vigencia = date; this.cotacao.dt_fin_vigencia = dateF;
问题原因
核心问题出在Date对象的属性设置顺序,以及JavaScript Date的自动溢出机制:
- 代码先通过
new Date()创建了一个以当前系统日期为基准的Date对象。比如当前日期如果是5月20日(5月只有30天),此时调用setDate(31),因为5月没有31日,Date会自动溢出,把日期调整为下一个月的第1天(也就是6月1日)。 - 后续再调用
setMonth和setFullYear修改年份和月份时,是基于已经变成6月1日的日期来调整的,最终得到的就是目标年份12月的1日——因为修改月份和年份不会改变日期的“日”部分,除非目标月份没有该日期,但12月有31天,所以1日会保留下来。
修复方案
有两种可靠的修复方式:
方式1:调整属性设置顺序
先设置年份和月份,最后设置日期,避免提前触发日期溢出:
var cotacaoJson = JSON.parse(resp[0].ds_cotacao_json); // 处理生效起始日期 var date = new Date(); date.setFullYear(cotacaoJson.dt_ini_vigencia.substring(0, 4)); date.setMonth(cotacaoJson.dt_ini_vigencia.substring(5, 7) - 1); date.setDate(cotacaoJson.dt_ini_vigencia.substring(8, 10)); // 最后设置日期 date.setHours(0, 0, 0, 0); // 合并设置时分秒,更简洁 // 处理生效结束日期 var dateF = new Date(); dateF.setFullYear(cotacaoJson.dt_fin_vigencia.substring(0, 4)); dateF.setMonth(cotacaoJson.dt_fin_vigencia.substring(5, 7) - 1); dateF.setDate(cotacaoJson.dt_fin_vigencia.substring(8, 10)); dateF.setHours(0, 0, 0, 0); this.cotacao = cotacaoJson; if (!this.editar) { this.cotacao.clausulas_particulares = 'N/A'; } this.cotacao.dt_ini_vigencia = date; this.cotacao.dt_fin_vigencia = dateF;
方式2:直接用原日期字符串构造Date对象(更简洁)
原JSON中的日期字符串是标准的ISO格式,直接传入Date构造函数即可正确解析,再重置时分秒即可:
var cotacaoJson = JSON.parse(resp[0].ds_cotacao_json); // 直接解析原日期字符串 var date = new Date(cotacaoJson.dt_ini_vigencia); date.setHours(0, 0, 0, 0); // 重置时分秒为0 var dateF = new Date(cotacaoJson.dt_fin_vigencia); dateF.setHours(0, 0, 0, 0); this.cotacao = cotacaoJson; if (!this.editar) { this.cotacao.clausulas_particulares = 'N/A'; } this.cotacao.dt_ini_vigencia = date; this.cotacao.dt_fin_vigencia = dateF;
内容的提问来源于stack exchange,提问作者Henrique Domanski
相关产品推荐
相关产品推荐

