获取Mongo DB中两个日期之间的工作日数

时间:2016-08-31 13:47:58

标签: mongodb date mongodb-query

我是Mongo DB的新手。任何人都可以帮助我如何获得两个给定日期之间的工作日数。

$ dayOfWeek 的日期将给出星期日的日期0和星期六的7日的价值。

但我的问题是如何将日期从开始日期增加到结束日期以查找工作日的数量。

示例数据:

 > db.data.insert({"startDate":ISODate('2016-0101'), "endDate":ISODate('2016-02-02')})  

    WriteResult({ "nInserted" : 1 })
    > db.data.find().pretty()
    { 
            "_id" : ObjectId("57c6e6a6a1e49d654caca17a"), 
            "startDate" : ISODate("2016-01-01T00:00:00Z"),
            "endDate" : ISODate("2016-02-02T00:00:00Z")
    }

现在需要查找开始日期(2016-01-01)和结束日期(2016-02-02)之间的工作日数。

我可以编写一个接受开始日期和结束日期的函数,但是在该函数中如何从开始日期到结束日期进行迭代?

请求任何帮助。

1 个答案:

答案 0 :(得分:3)

要查找2个日期之间的工作日总数,您可以从总天数中减去周末总数。这里的主要问题是找到总周末数。

示例 [2016-12-23; 2017年1月1日]

  

_Dec23 ___ Dec24 ___ Dec25 ____... ____ Dec30 ___ Dec31 ___ Jan01 ___...

     

__星期五星期六______ _____太阳______...______星期五星期六_____ _____太阳_____...

如您所见,这些日期之间有4个周末(Dec24,Dec25,Dec31和Jan01)。

<强>解决方案

以编程方式解决此问题的一种方法是将聚合框架算术日期聚合运算符一起使用。

可以将任务分成2个子任务来完成:

  1. startDateendDate之间查找整周的数量(将其命名为weeksBetween)。在上面的示例中weeksBetween = 1
  2. startDate + 7 * weeksBetweenendDate之间查找全天的数量(将其命名为left,可以是1,2,3,4,5或6 )。在上面的例子中left = 3(左边是星期五,星期六和星期日)。有趣的是那些剩下的日子里的周末数量(命名为left_weekends,它可以是0,1或2)。在上面的示例中left_weekends = 2
  3. 然后,周末总数为2 * weeksBetween + left_weekends。在上面的示例中,它是2 * 1 + 2 = 4

    要查找left_weekends,您可以使用$dayOfWeek 日期汇总运算符

    1. 适用于Sun dayOfWeek = 1left_weekends = 1如果left为1,2,3,4,5或left_weekends = 2,如果left为6(包括Sun和下周六)。
    2. 代表dayOfWeek = 2left_weekends = 0如果left为1,2,3,4或left_weekends = 1 left为5或left_weekends = 2如果left为6(包括下周六和周日)。
    3. ...

        对于任何dayOfWeek = 7,星期六left_weekends = 2left
      1. 因此,我们可以使用下一个规则:

        1. 如果remainder > 7,则left_weekends = 2

        2. 如果remainder = 7,那么周一至周六为left_weekends = 1,而对于Sun则为left_weekends = 2

        3. 如果remainder < 7那么周一至周六为left_weekends = 0,而对于Sun则为left_weekends = 1

        4. 此处remainder = dayOfWeek + left

          <强>查询

          db.dates.aggregate(
            {
              $project:
                {
                  "daysBetween":
                    {
                      $add: [
                        {
                          $floor:
                            {
                              $divide: [
                                { $subtract: [ "$endDate", "$startDate" ] },
                                1000 * 60 * 60 * 24
                              ]
                            }
                        },
                        1
                      ]
                    },
                  "startDay": { $dayOfWeek: "$startDate" },
                  "endDay": { $dayOfWeek: "$endDate" }
                }
            },
            {
              $project:
                {
                  "daysBetween": "$daysBetween",
                  "weeksBetween": { $floor: { $divide: [ "$daysBetween", 7 ] } },
                  "startDay": "$startDay",
                  "remainder":
                    {
                      $add: [
                        { $abs: { $subtract: [ "$endDay", "$startDay" ] } },
                        "$startDay"
                      ]
                    }
                }
            },
            {
              $project:
                {
                  "weekendsBetween":
                    {
                      $add: [
                        { $multiply: [ "$weeksBetween", 2 ] },
                        {
                          $cond:
                            {
                              if: { $gt: [ "$remainder", 7 ] },
                              then: 2,
                              else:
                                {
                                  $cond:
                                    {
                                      if: { $eq: [ "$remainder", 7 ] },
                                      then: 1,
                                      else: 0
                                    }
                                }
                            }
                        },
                        { $cond: { if: { $eq: [ "$startDay", 1 ] }, then: 1, else: 0 } }
                      ]
                    },
                  "daysBetween": "$daysBetween"
                }
            },
            {
              $project:
                {
                  "weekdaysBetween": { $subtract: [ "$daysBetween", "$weekendsBetween" ] }
                }
            }
          );
          

          <强>示例

          { "_id": 1, "startDate": ISODate("2016-12-23T00:00:00Z"), 
                      "endDate":   ISODate("2017-01-01T00:00:00Z") }
          { "_id": 2, "startDate": ISODate("2016-12-23T00:00:00Z"), 
                      "endDate":   ISODate("2017-01-09T00:00:00Z") }
          { "_id": 3, "startDate": ISODate("2016-12-23T00:00:00Z"), 
                      "endDate":   ISODate("2017-01-18T00:00:00Z") }  
          

          <强>结果

          { "_id": 1, "weekdaysBetween" : 6 }
          { "_id": 2, "weekdaysBetween" : 12 }
          { "_id": 3, "weekdaysBetween" : 19 }
          

          PS 延长最后$project阶段,您还可以获得2个日期之间的总天数和周末数。在测试查询之前,不要忘记更改集合名称。