我想测试下面的代码。我想知道是否有一种方法可以模拟moment.js
或强制它认为我的当前位置是America/New_York
,这样我的单元测试就不会在www.example.com runner中失败gitlab.ci,因为它可能位于不同的地理位置?
const centralTimeStartOfDay = moment.tz('America/Chicago').startOf('day');
const startHour = centralTimeStartOfDay
.hour(7)
.local()
.hour();
基本上,我希望硬编码我的时区为America/New_York
,并希望此函数的行为一致。
编辑:
我试过:
Date.now = () => new Date("2020-06-21T12:21:27-04:00")
moment.tz.setDefault('America/New_York')
我仍然得到了相同的结果,我想模拟当前时间,这样startHour
就能返回一个一致的值。
3条答案
按热度按时间vtwuwzda1#
问题是
所以这个问题没有一行字的答案,这个问题是javascript的一个基本问题,你可以用两种方式之一查看日期:
1.协调世界时(一月一日、一月一日等)
1.本地(即系统、
getHours()
、getMinutes()
等)而且没有指定的方法来设置有效的系统时区,甚至UTC偏移量。
(Scan通过mdn
Date
reference或检查规范,以了解这一切是多么没有帮助。)"等等!"我们喊道,"这不就是
moment-timezone
存在的原因吗?"不完全是这样,
moment
和moment-timezone
在javascript中提供了更好/更容易的时间管理控制,但即使是它们也无法知道Date
使用的是什么本地时区,并使用其他机制来了解它。了解了代码之后,您将看到moment的
.local()
方法(setOffsetToLocal的原型声明和实现)有效地执行了以下操作:_isUTC
设置为false禁用"UTC模式"。禁用"UTC模式"的效果是意味着大多数访问器方法被转发到底层的
Date
对象。例如.hours()
最终调用moment/get-set. jsget()
,如下所示:_d
是时刻(mom
)正在 Package 的Date
对象。因此,对于非UTC模式时刻,moment.hours()
有效地传递到Date.prototype.getHours()
。您用moment.tz.setDefault()
设置了什么,或者是否覆盖了Date.now()
,都不重要。还有一件事...
你说:
基本上,我希望将时间硬编码为America/New_York,并希望此函数的行为保持一致
但实际上,这通常是不可能的。你使用的是芝加哥,我想芝加哥与纽约同步抵消了时差,但例如,英国时差与美国时差不同,所以如果你从美国时区转换到英国时区,一年中会有几周测试失败。
解决方案。
但这仍然令人沮丧,因为我不希望我在波兰和美国西海岸的开发人员因为我的CI服务器在UTC运行而破坏本地测试。
第一个解决方案不是一个解决方案:找到一种不同的方法来做你正在做的事情!通常使用
.local()
的用例是相当有限的,并且是向用户显示他们的 * 当前偏移量 * 中的时间。它甚至不是他们的时区,因为本地Date
方法只会查看当前偏移量。所以大多数时候你只想使用它来表示当前时间,或者如果您不介意它对一半的Date
对象是错误的(对于使用夏令时的时区),那么通过其他方式了解用户想要的时区可能会更好,而根本不使用.local()
。第二个解决方案也不是一个解决方案:别太担心你的测试!显示本地时间的主要问题是它能正常工作,你并不关心它到底是什么。手动验证它显示的时间是否正确,在测试中验证它返回的时间是否合理,而不检查具体的时间。
如果你还想继续,最后一个解决方案至少可以让你的案例和其他一些案例工作,如果你发现你需要扩展它,你需要做什么是显而易见的。然而,这是一个复杂的领域,我不保证这不会有一些意想不到的副作用!
在测试设置文件中:
现在您应该能够使用
moment.tz.setDefault()
,并且使用.local()
应该允许您访问datetime的属性,就好像它认为本地时区是在moment-timezone
中配置的一样。我想过尝试修补
moment
,但它比Date
复杂得多,修补Date
应该是健壮的,因为它是原始的。tag5nh1u2#
尝试
laik7k3q3#
非常棒的daphtdazz -谢谢!为了向读者说明,这是我用来控制当前日期、时区的完整解决方案,在daphtdazz的帮助下-local()行为in moment: