如何使用moment实现LocalStorage存储值当日午夜后过期
完全可以用moment实现需求,现有逻辑的核心问题是仅存储了YYYY-MM-DD格式的日期字符串,没有记录精确的过期时间节点,无法完成可靠的时间比对。
具体实现步骤
1. 改造按钮点击时的存储逻辑
点击按钮写入LocalStorage时,直接用moment计算出当日午夜的时间戳,和点击标记一起序列化后存储:
const setVarReservation = () => { // 计算当日结束(次日0点前1毫秒)的时间戳,作为过期节点 const expireTimestamp = moment().endOf('day').valueOf(); const storageData = { isClicked: true, expireAt: expireTimestamp }; window.localStorage.setItem('alertToBeSetted', JSON.stringify(storageData)); };
moment().endOf('day')会自动获取当前用户本地时区下当日的最后一毫秒对应的时间对象,转成数值时间戳后,只要当前时间超过这个值,就代表已经过了当日午夜,标记失效。以20:00点击的场景为例,计算出的过期时间就是当日23:59:59.999,刚好覆盖后续到午夜的4小时,完全匹配需求。
2. 改造登录时的校验逻辑
在登录触发的saga中,通过时间戳数值比对判断标记是否过期,逻辑如下:
const checkButtonVisible = () => { const storageRaw = window.localStorage.getItem('alertToBeSetted'); // 无存储标记,直接展示按钮 if (!storageRaw) return showButton(); const { expireAt } = JSON.parse(storageRaw); const currentTimestamp = Date.now(); // 当前时间超过过期时间,清除存储、展示按钮 if (currentTimestamp > expireAt) { window.localStorage.removeItem('alertToBeSetted'); return showButton(); } // 未过有效期,隐藏按钮 return hideButton(); };
可选无依赖实现方案
如果不想引入moment,用原生JavaScript的Date对象也可以实现完全一致的效果,不需要额外依赖:
// 原生计算当日午夜时间戳 const getTodayMidnightTs = () => { const now = new Date(); const midnight = new Date( now.getFullYear(), now.getMonth(), now.getDate() + 1, // 日期+1切到次日 0, 0, 0 // 时分秒置为0,即次日0点 ); return midnight.getTime(); };
注意事项
- 不要直接用日期字符串做大小比对,字符串按字典序比较在跨日、跨月、跨年场景下很容易出现判断错误,用数值型时间戳做比较是最稳妥的方案
- 如果业务要求统一按指定时区(而非用户本地时区)计算午夜时间,给moment配置对应时区参数、或给原生Date计算加对应时区偏移即可
- 如果存在用户长时间挂起页面不刷新的场景,可以加一个一次性定时器,在计算出的午夜时间点自动触发一次校验,避免页面不刷新就一直不展示按钮的问题
内容的提问来源于stack exchange,提问作者Levi D.
相关产品推荐
相关产品推荐

