Nod*_*.JS 4 javascript momentjs jestjs
我想测试下面的一段代码。我想知道是否有办法模拟moment.js或强制它认为我当前的位置是America/New_York这样我的单元测试不会在 gitlab.ci runner 中失败,它可能位于不同的地理位置?
const centralTimeStartOfDay = moment.tz('America/Chicago').startOf('day');
const startHour = centralTimeStartOfDay
.hour(7)
.local()
.hour();
Run Code Online (Sandbox Code Playgroud)
基本上我想对我的时区进行硬编码,America/New_York并希望这个函数的行为一致。
编辑:
我试过:
Date.now = () => new Date("2020-06-21T12:21:27-04:00")moment.tz.setDefault('America/New_York')而且,我得到了相同的结果。我想模拟当前时间,以便startHour返回一致的值。
所以这个问题没有一行答案。这个问题是 javascript 的一个基本问题,您可以通过以下两种方式之一查看日期:
getUTCHours(),getUTCMinutes()等等)getHours(),getMinutes()等等)并且没有指定的方法来设置有效的系统时区,甚至是 UTC 偏移量。
(浏览mdnDate参考或查看规范以了解这一切是多么无用。)
“可是等等!” 我们哭了,“这不就是为什么moment-timezone存在吗??”
不完全是。moment并moment-timezone在 javascript 中更好/更轻松地控制管理时间,但即使他们也无法知道本地时区Date正在使用什么,并使用其他机制来了解这一点。这是一个如下问题。
一旦你了解了代码,你就会看到 moment 的 moment.local()方法(setOffsetToLocal 的原型声明和实现)有效地执行以下操作:
_isUTC为 false禁用“UTC 模式” 。禁用“UTC 模式”的效果是意味着大多数访问器方法被转发到底层Date对象。例如,.hours()最终调用moment/get-set.jsget(),如下所示:
export function get(mom, unit) {
return mom.isValid()
? mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]()
: NaN;
}
Run Code Online (Sandbox Code Playgroud)
_d是Date时刻 ( mom) 包裹的对象。对于非 UTC 模式时刻如此有效,moment.hours()是对Date.prototype.getHours(). 无论您设置了什么moment.tz.setDefault(),或者您是否覆盖了Date.now(). 这些东西都没有使用。
你说:
基本上我想硬编码我的时间是 America/New_York 并希望这个函数的行为一致
但实际上,这通常是不可能的。您正在使用芝加哥,我认为它与纽约同步偏移,但例如,英国在与美国不同的时间转移,因此如果您从美国时区到英国时区。
但这仍然令人沮丧,因为我不希望我在波兰和美国西海岸的开发人员因为我的 CI 服务器在 UTC 中运行而进行破坏性的本地测试。那么我们能做些什么呢?
第一个解决方案是一个非解决方案:找到一种不同的方式来做你正在做的事情!通常使用的用例.local()非常有限,并且是向用户显示其当前偏移量中的时间。它甚至不是他们的时区,因为本地Date方法只会查看当前的偏移量。因此,大多数情况下,您只想在当前时间使用它,或者如果您不介意使用它的一半Date对象是否错误(对于使用夏令时的时区)。最好通过其他方式了解用户想要的时区,而根本不使用.local()。
第二种解决方案也是一个非解决方案:不要太担心你的测试!显示本地时间的主要事情是它有效,您并不真正关心它到底是什么。手动验证它显示的时间是否正确,并且在您的测试中只验证它返回一个看起来合理的东西,而不检查特定时间。
如果您仍然想继续,最后一个解决方案至少可以使您的案例和其他一些解决方案起作用,并且如果您发现需要扩展它,您需要做什么很明显。然而,这是一个复杂的领域,我不保证这不会有一些意想不到的副作用!
在您的测试设置文件中:
[
'Date',
'Day',
'FullYear',
'Hours',
'Minutes',
'Month',
'Seconds',
].forEach(
(prop) => {
Date.prototype[`get${prop}`] = function () {
return new Date(
this.getTime()
+ moment(this.getTime()).utcOffset() * 60000
)[`getUTC${prop}`]();
};
}
);
Run Code Online (Sandbox Code Playgroud)
您现在应该能够使用moment.tz.setDefault()并且使用.local()应该允许您访问日期时间的属性,就好像它认为本地时区与moment-timezone.
我想过尝试修补
moment,但它比 复杂得多Date,而且修补Date应该很健壮,因为它是原始的。
| 归档时间: |
|
| 查看次数: |
1053 次 |
| 最近记录: |