moment.js - 检查两个时刻是不是来自同一周,但周从周五开始到周四结束

Posted

技术标签:

【中文标题】moment.js - 检查两个时刻是不是来自同一周,但周从周五开始到周四结束【英文标题】:moment.js - Check if two moments are from the same week, but weeks begin on Friday and end on Thursdaymoment.js - 检查两个时刻是否来自同一周,但周从周五开始到周四结束 【发布时间】:2017-11-03 21:21:12 【问题描述】:

我正在使用 node.js 和 discord.js 创建一个 Discord 机器人,并且有一个功能允许用户通过命令进行投票,但我希望他们每周只投票一次。

问题是,在这个 Discord 中,每周从周五开始,到周四结束,因此我不能简单地写:

var weekNow = moment().week();
var weekLastVote = moment(dateLastVote).week();
if (weekNow == weekLastVote)
    //Prevent from voting again
 else 
    //Let the user vote

因此,我编写了一些似乎可以工作的代码,但我想听听你的意见,因为它看起来很草率,我不确定我是否考虑了所有可能性(我不例如,知道我是否需要使用我的 month 变量):

module.exports = 
isSameWeek: function (dateLastVote) 
    // moments for today's date
    var dayNow = moment().weekday();
    var weekNow = moment().week();
    var monthNow = moment().month();
    var yearNow = moment().year();
    var dateNow = moment().format('MMDDYYYY'); // moment without hours/minutes/seconds

    // moments for last vote's date
    var dayLastVote = moment(dateLastVote).weekday();
    var weekLastVote = moment(dateLastVote).week();
    var monthLastVote = moment(dateLastVote).month();
    var yearLastVote = moment(dateLastVote).year();
    var dateLastVote = moment(dateLastVote).format('MMDDYYYY'); // moment without hours/minutes/seconds

    if ((yearNow === yearLastVote && weekNow === weekLastVote && dayLastVote < 5) || // 5 = Friday, starting day of the week (a week = Friday to thursday)
        (yearNow === yearLastVote && weekNow - 1 === weekLastVote && dayLastVote >= 5 && dayNow < 5) || 
        (dateNow === dateLastVote)
    )
        return true;
     else 
        return false;
    

;

正如我所说,这似乎可以解决问题,但我希望其他人对此发表意见,以确保没有更简单的方法,或者,如果没有,如果我没有忘记任何东西。

感谢您的阅读:)

【问题讨论】:

您至少可以将moment()moment(dateLastVote) 的结果存储在变量中,而不是重复调用它们。 是的,这是真的。我还没有真正完善代码,我只是想弄清楚哪些有效,哪些无效,所以我并没有真正考虑过。 【参考方案1】:

我不知道我们的方法在性能方面如何比较,但我仍然想展示我在这个问题上的方法:

function isSameWeek(firstDay, secondDay, offset) 
    var firstMoment = moment(firstDay);
    var secondMoment = moment(secondDay);

    var startOfWeek = function (_moment, _offset) 
        return _moment.add("days", _moment.weekday() * -1 + (_moment.weekday() >= 7 + _offset ? 7 + _offset : _offset));
    

    return startOfWeek(firstMoment, offset).isSame(startOfWeek(secondMoment, offset), "day");

解决方案的作用是计算每个给定日期相对于偏移量的一周的开始时间(对于值 >= -7 和

您所要做的就是调用传递两个日期对象(或时刻对象)的函数以及 -7 和 0 之间的偏移量,具体取决于周相对于“常规”周的移动方式。

【讨论】:

我现在不能尝试,但我会告诉你它是否有效。不过,它看起来确实比我的方法更干净,就是这样。 因此,如果我想让星期五成为一周的第一天,我必须将 offset 设置为 -3,因此它是星期一前 3 天,即星期五?还是我误解了什么?此外,您需要将return _moment.add("days", _moment.weekday() * -1 + (_moment.weekday() &gt;= 7 + _offset ? 7 + _offset : _offset)); 更改为return _moment.add(_moment.weekday() * -1 + (_moment.weekday() &gt;= 7 + _offset ? 7 + _offset : _offset), "days");,因为第一个现在显然已弃用。 好的,我现在已经尝试了您的解决方案,它似乎工作正常。我将偏移量设置为 -2,所以它是星期天 - 2 天,我还没有看到该解决方案有任何问题,所以它应该很好。谢谢:) @Tokipudi 请VincenzoC的解决方案我很喜欢。【参考方案2】:

根据 Moment 文档,您可以设置 ISO 一周的开始时间:

moment().isoWeekday(1); // Monday
moment().isoWeekday(7); // Sunday

然后您可以使用相同的功能来检查日期是否在一年中的同一周。

看看: https://momentjs.com/docs/#/get-set/iso-weekday/

【讨论】:

这似乎只适用于值 1 和 7。刚刚测试过,像 5 这样的值对我不起作用。 正如@Kevkong 所说,它在周一和周日以外的任何日子都不起作用。此功能主要用于在现有的两个最常见的日历之间切换:从星期日开始的日历(如果我没记错的话,就像在美国一样)和从星期一开始的日历(比如在法国)【参考方案3】:

我认为最好的方式是告诉你你的一周从星期五开始。您可以简单地使用updateLocale 方法自定义week 对象的dow(星期几)键,然后使用您的第一个代码sn-p。请参阅文档的Customize 部分以获取有关区域设置自定义的更多信息。

这是一个将自定义日期设置为一周的第一天然后使用您的代码检查给定日期是否在当前周内的实时示例:

moment.updateLocale('en', 
  week: 
    dow : 5, // Friday is the first day of the week.
  
);

function checkWeek(dateLastVote)
  var weekNow = moment().week();
  var weekLastVote = moment(dateLastVote).week();
  if (weekNow == weekLastVote)
      //Prevent from voting again
      console.log(moment(dateLastVote).format('YYYY-MM-DD') + ' is in the current week')
   else 
      //Let the user vote
      console.log(moment(dateLastVote).format('YYYY-MM-DD') + ' is NOT in the current week')
  


checkWeek('2017-05-30'); // same week mon-sun, but previous week fri-thu
checkWeek('2017-06-01'); // same week mon-sun, but previous week fri-thu
checkWeek('2017-06-08'); // next week mon-sun, but current week fri-thu

// First day of the current week
console.log(moment().startOf('week').format('YYYY-MM-DD'));
// Last day of the current week
console.log(moment().endOf('week').format('YYYY-MM-DD'));
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"&gt;&lt;/script&gt;

EDIT 一种改进的解决方案是使用矩 isSame 传递 'week' 作为第二个参数。正如文档所述:

检查一个时刻是否与另一个时刻相同。

如果要将粒度限制为毫秒以外的单位,请将其作为第二个参数传递。

这是一个现场样本:

moment.updateLocale('en', 
  week: 
    dow : 5, // Friday is the first day of the week.
  
);

function isSameWeek(dateLastVote)
  var now = moment();
  var lastVote = moment(dateLastVote);
  if (now.isSame(lastVote, 'week'))
      //Prevent from voting again
      console.log(moment(dateLastVote).format('YYYY-MM-DD') + ' is in the current week')
   else 
      //Let the user vote
      console.log(moment(dateLastVote).format('YYYY-MM-DD') + ' is NOT in the current week')
  


isSameWeek('2017-06-10'); // same week mon-sun, but next week fri-thu
isSameWeek('2017-06-03'); // previous week mon-sun, but current week fri-thu
isSameWeek('2017-06-06'); // current week both mon-sun and fri-thu

// First day of the current week
console.log(moment().startOf('week').format('YYYY-MM-DD'));
// Last day of the current week
console.log(moment().endOf('week').format('YYYY-MM-DD'));
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"&gt;&lt;/script&gt;

【讨论】:

我认为这比我的回答要好。

以上是关于moment.js - 检查两个时刻是不是来自同一周,但周从周五开始到周四结束的主要内容,如果未能解决你的问题,请参考以下文章

尝试在 moment.js 中转换 RFC2822 日期时出现“弃用警告:时刻构造回退到 js 日期”

使用moment.js解析时如何忽略时区

“时刻”没有导出成员“默认”

moment.js,如何获取星期几

moment.js能判断是不是为节假日吗

Moment.js 没有显示正确的时间