C#解析Redis中JSON字符串时DateTime时区信息丢失问题
解决Redis中带时区的DateTime解析时丢失时区信息的问题
这个问题我之前也帮别人排查过,核心是你用的Newtonsoft.Json(JObject所属的库)默认解析逻辑会自动剥离时区信息,导致你看不到原始的+00:00标记。下面给你几个实用的解决方案:
方案1:直接保留字符串形式(最简单)
如果你的业务不需要把expiry当作DateTime类型处理,只是需要原样存储和读取,直接把它当作字符串提取就行:
RedisValue cookie = GetRedisDatabase().StringGet("sessionhash"); JObject cookieValue = JObject.Parse(cookie.ToString()); var expiryFullStr = cookieValue["expiry"].ToString(); // 这里拿到的就是完整的"2018-03-19T23:00:03.0658822+00:00"字符串
方案2:配置Json解析器保留时区信息
如果需要把expiry转换成DateTime/DateTimeOffset类型,修改解析设置让它保留时区:
// 配置解析器保留时区信息 var jsonSettings = new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind }; RedisValue cookie = GetRedisDatabase().StringGet("sessionhash"); // 解析JObject时也要指定对应设置 JObject cookieValue = JObject.Parse(cookie.ToString(), new JsonLoadSettings { DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind }); // 转换成DateTimeOffset(推荐,能完整保留偏移量) var expiryOffset = cookieValue["expiry"].ToObject<DateTimeOffset>(JsonSerializer.Create(jsonSettings)); // 或者转换成带Utc标记的DateTime var expiryDateTime = cookieValue["expiry"].ToObject<DateTime>(JsonSerializer.Create(jsonSettings)); // 此时expiryDateTime.Kind会是DateTimeKind.Utc,时区信息通过Kind属性保留
为什么这个有用?因为Newtonsoft.Json默认的DateTimeZoneHandling是Local,会把带时区的时间转成本地时区的DateTime并剥离原始偏移;而RoundtripKind会严格保留原始时区信息,对于+00:00的字符串会解析成Utc类型的DateTime,或者完整的DateTimeOffset。
方案3:绑定到实体类(更规范)
如果有对应的业务实体类,直接反序列化会更清晰:
// 定义实体类 public class SessionData { public string Email { get; set; } // 用DateTimeOffset能直接存储偏移量,推荐 public DateTimeOffset Expiry { get; set; } // 也可以用DateTime,配合下面的JsonSettings // public DateTime Expiry { get; set; } } // 反序列化时指定设置 var jsonSettings = new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind }; RedisValue cookie = GetRedisDatabase().StringGet("sessionhash"); SessionData session = JsonConvert.DeserializeObject<SessionData>(cookie.ToString(), jsonSettings); // session.Expiry会包含完整的时区偏移信息
内容的提问来源于stack exchange,提问作者Sun
相关产品推荐
相关产品推荐

