Kotlin Multiplatform项目中kotlin.js.Date相等校验不生效如何解决?
问题根因
你的推测完全正确,kotlin.js.Date 本质是对JS原生Date对象的封装,原生JS Date的==是引用比较,Kotlin也没有为该类默认重载equals方法,所以两个时间戳相同但实例不同的Date对象会被判定为不相等,而JVM的java.util.Date和Native的NSDate都重写了按时间比较的equals方法,因此校验通过。
可选解决方案(按侵入性从低到高排序)
方案1:仅自定义测试断言(零侵入,优先推荐)
如果仅在单元测试场景需要做Date相等校验,完全不需要修改生产代码,只需在测试模块新增跨平台的Date断言工具即可:
- 在commonTest源集声明expect方法:
expect fun assertDateEquals(expected: Date, actual: Date, message: String? = null)
- 各平台实现:
- JVM/Native的actual实现直接调用原有assertEquals即可:
actual fun assertDateEquals(expected: Date, actual: Date, message: String?) { assertEquals(expected, actual, message) }
- JS的actual实现按时间戳比较:
actual fun assertDateEquals(expected: Date, actual: Date, message: String?) { assertEquals(expected.getTime(), actual.getTime(), message) }
后续所有Date比较的测试用例统一调用assertDateEquals即可,完全不需要改动现有生产API。
方案2:JS侧重载Date的equals运算符(低侵入)
如果生产代码中也有大量Kotlin侧的Date相等判断逻辑,不想改动现有Date的声明,可以直接在JS源集新增运算符重载:
// JS源集下添加 operator fun kotlin.js.Date.equals(other: Any?): Boolean { if (this === other) return true if (other !is kotlin.js.Date) return false return this.getTime() == other.getTime() } // 同步重写hashCode避免Hash集合类使用时出现异常 fun kotlin.js.Date.hashCode(): Int { return getTime().toInt() }
该方案不需要改动现有公共API,仅需添加两个扩展方法,缺点是如果Date对象会被传递到原生JS代码中,JS侧的相等判断还是会走引用比较,仅Kotlin侧的==调用会生效。
方案3:Value Class包装公共Date类(长期最优)
如果你的项目后续还需要对Date做跨平台的统一操作(比如日期计算、格式化等),推荐用内联值类包装时间戳实现公共Date:
// common源集 @JvmInline expect value class Date(val timestampMs: Long)
各平台的actual实现可以保留与平台原生Date的互转方法,原有业务代码中使用公共Date的地方不需要修改,对外API完全兼容:
- 自动获得全平台统一的equals、hashCode、toString实现,不需要手动重写
- 无额外性能开销,值类会在编译时被解包为原生Long
- 后续可以统一在common层扩展日期操作方法,不用各平台重复实现
内容的提问来源于stack exchange,提问作者Daan
相关产品推荐
相关产品推荐

