【问题标题】:Algorithm to group messages by time按时间分组消息的算法
【发布时间】:2017-09-21 14:07:51
【问题描述】:

我需要按以下顺序对消息进行排序:收到的TodayYesterdayThis Week

This Week 的规则:从最近的星期一开始 - 不包括 TodayYesterday

意思:

如果Today 是星期日,Yesterday 是星期六,This Week 是星期五、星期四、星期三、星期二和星期一

如果Today 是星期四,Yesterday 是星期三,This Week 是星期二和星期一

但如果Today 是星期二,Yesterday 是星期一 -- This Week 没有日子

如果Today 是星期一,Yesterday 是星期日 -- This Week 没有日子

我一直在努力弄清楚如何解决This Week。我不断遇到错误,还有很多边缘情况需要考虑。

这是我的尝试:

var currentDate = new Date()
var currentMonth = currentDate.getMonth()+1
var currentYear = currentDate.getFullYear()
var currentDayofMonth = currentDate.getDate()
var currentDayofWeek = currentDate.getDay()
messages.forEach((message, index) => {
   var date = message.date.substring(0, 10).replace(/-/g, '\/')
   var messageDate = new Date(date)
   var messageMonth = messageDate.getMonth()+1;
   var messageYear = messageDate.getFullYear();
   var messageDayOfMonth = messageDate.getDate();
   var messageDayOfWeek = messageDate.getDay();

   //TODAY
   if(currentDayofMonth == messageDayOfMonth && currentMonth == messageMonth && currentYear == messageYear) {
     messageTypeList["Today"].push(message)
     return
   }

   //YESTERDAY
   if(currentDayofMonth == messageDayOfMonth+1 && currentMonth == messageMonth && currentYear == messageYear) {
     messageTypeList["Yesterday"].push(message)
     return
   }

    //THIS WEEK
    if(currentDayofWeek != 1 && currentDayofWeek != 2 && currentMonth == messageMonth && currentYear == messageYear) {
      messageTypeList["This Week"].push(message)
      return
    }
})

有什么想法吗?

注意

我相信我在 Yesterday 中有一个极端情况错误 -- 例如,如果 Today 是 5 月 1 日,则不会将 4 月 30 日算作 Yesterday,因为月份不同

【问题讨论】:

    标签: javascript algorithm date timestamp


    【解决方案1】:

    您可以通过准备一些与今天日期相关的日期来更好地准备地面:

    • 将当前日期截断为午夜
    • 获取昨天的日期
    • 获取上周一的日期

    然后将消息日期与这 3 个日期中的每一个日期进行比较:消息日期之前或之前的第一个日期决定了消息的类别。如果这三个都大于消息日期,则不需要发生任何事情。

    这是建议的代码:

    // This sample uses a fixed date so the categories can be illustrated better:
    var currentDate = new Date('2017/04/27') // Or leave out the argument for actual date
    currentDate.setHours(0,0,0,0); // set to midnight
    // Prepare all related dates: yesterday and last Monday
    var keys = [];
    keys.push(['Today', new Date(currentDate)]); // clone
    currentDate.setDate(currentDate.getDate() - 1);
    keys.push(['Yesterday', new Date(currentDate)]); // clone
    currentDate.setDate(currentDate.getDate() - (currentDate.getDay()+6)%7);
    keys.push(['This week', new Date(currentDate)]); // clone
    
    var messages = [
        { date: '2017-04-21' },
        { date: '2017-04-22' },
        { date: '2017-04-23' },
        { date: '2017-04-24' }, // Monday
        { date: '2017-04-25' },
        { date: '2017-04-26' },
        { date: '2017-04-27' },
    ];
    
    var messageTypeList = {
        Today: [],
        Yesterday: [],
        "This week": []
    };
    
    messages.forEach( message => {
        var date = message.date.substring(0, 10).replace(/-/g, '\/');
        var messageDate = new Date(date);
        var [key] = keys.find( ([key, date]) => messageDate >= date ) || [];
        if (key) messageTypeList[key].push(message);
    });
    
    console.log(messageTypeList);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    输出:

    {
      "Today": [
        {
          "date": "2017-04-27"
        }
      ],
      "Yesterday": [
        {
          "date": "2017-04-26"
        }
      ],
      "This week": [
        {
          "date": "2017-04-24"
        },
        {
          "date": "2017-04-25"
        }
      ]
    }
    

    这种工作方式(使用setHourssetDate)可以很好地处理由于夏令时开关而变短/变长的时区和天数,只要您将字符串传递给位于本地的Date()时区。所以他们不应该指定不同的时区(例如,没有Z 或没有YYYY-MM-DD 表示法)。

    【讨论】:

    • 非常感谢。非常有用和聪明的方法。但是如果今天是 27,昨天是 26,那么本周应该是 25 和 24。看起来你的尝试可能有错误?
    • 你得到不同的输出吗?我添加了脚本为我提供的输出。
    • 奇怪,当我运行代码 sn-p 我得到这个输出:{ "Today": [ { "date": "2017-04-26" }, { "date": "2017-04-27" } ], "Yesterday": [ { "date": "2017-04-25" } ], "This week": [ { "date": "2017-04-24" } ] }
    • 啊,找到了。我应该在日期符号中使用斜杠来设置currentDate。现已更正。它以前对我有用,因为我在 GMT+1,但是当在 GMT-6 或其他负面的时候,结果会很糟糕。使用斜线,日期被解释为在本地时区。通常你只会使用new Date() 来完成那个任务,我在将它更改为更有趣的日期时引入了错误 ;-)
    【解决方案2】:

    首先:将您的代码分离为函数。测试和调试会容易得多。 其次,添加“else”,并在 thisWeek() 中计算上一个星期一(作为日期)并检查当前日期是否大于此日期(如果日期在上一个星期一之后) - 示例 messageDate.getTime() >= lastMondayDate.getTime()

    唯一要做的就是计算最后一个星期一

    伪:

    if (isToday(message, currentDate)){
     messageTypeList["Today"].push(message)
    } else if (isYesterday(message, currentDate)){
     messageTypeList["Yesterday"].push(message)
    } else if (isThisWeek(message, currentDate)) {
          messageTypeList["This Week"].push(message)
    }
    

    【讨论】:

      猜你喜欢
      • 2017-09-06
      • 1970-01-01
      • 1970-01-01
      • 2015-03-05
      • 1970-01-01
      • 1970-01-01
      • 2012-08-09
      • 1970-01-01
      相关资源
      最近更新 更多