iOS端Date()返回小时超24致服务器日期存储NULL问题求助
哇,这个小时数变成77的问题真的有点离谱!让我帮你理清楚问题出在哪,以及怎么解决:
首先,先拆解核心问题:你遇到的两个症状(服务器存NULL、Date字符串输出77小时)其实根源是同一个——你在日期格式处理上依赖了不可靠的机制。
为什么会出现77小时的诡异输出?
当你直接用\(Date())把日期转成字符串时,你用的是Date类的默认description方法,这个方法的输出是给开发者调试用的,完全没有固定的格式规范,它会受系统locale、时区甚至app内其他代码修改的全局设置影响。
比如,如果你的app里有其他地方不小心修改了全局的日期格式化配置(比如错误地给某个DateFormatter设置了奇怪的dateFormat,或者修改了系统calendar的属性),就可能导致这个解析异常,出现77这种不可能的小时数。但不管怎样,这个默认字符串从来不是为机器间数据传输设计的,绝对不能用来发给服务器。
为什么最初的格式化代码会导致服务器存NULL?
你最初的代码逻辑本身没问题,但有一个关键的隐患:你用了NSLocale.current作为DateFormatter的locale。系统的当前locale会随用户的区域设置变化,比如在某些非英语区域,这个locale可能会导致日期字符串的格式出现细微差异(比如月份的缩写、分隔符等),而C#那边的日期解析器如果是按固定格式来的,就会解析失败,最终存成NULL。
正确的解决方案
这里给你两个可靠的方案,优先选第一个:
方案1:直接发送时间戳(最稳妥)
完全跳过字符串格式化的环节,把日期转成毫秒级时间戳发给服务器:
let timestamp = Date().millisecondsSince1970 // 这是Int64类型的毫秒数 self.backS.sendLocation(msg: "data fitched \(timestamp)")
服务器端C#可以直接用DateTimeOffset.FromUnixTimeMilliseconds(timestamp).UtcDateTime把时间戳转成UTC时间,完全不会有解析错误的问题。
方案2:使用标准格式化字符串(修正后的代码)
如果必须发字符串,一定要用固定的locale和UTC时区,确保格式绝对一致:
let date = Date() let dateFormatter = DateFormatter() dateFormatter.timeZone = TimeZone(abbreviation: "UTC") // 关键:用en_US_POSIX locale,这个是专门为机器解析设计的,不受系统区域影响 dateFormatter.locale = Locale(identifier: "en_US_POSIX") dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" let dateString = dateFormatter.string(from: date) self.backS.sendLocation(msg: "data fitched \(dateString)")
这样生成的字符串格式完全固定,C#那边按相同的格式解析就不会出错了。
另外要注意:DateFormatter不是线程安全的,如果你的代码在多线程环境下使用,最好每个线程单独创建实例,或者加锁保护。
内容的提问来源于stack exchange,提问作者Yaqeen Raddad

