【问题标题】:How do I calculate the date in JavaScript three months prior to today?如何计算今天前三个月的 JavaScript 日期?
【发布时间】:2011-10-29 05:44:21
【问题描述】:

我正在尝试形成一个比当前日期早 3 个月的日期。我通过以下代码获取当前月份

var currentDate = new Date();
var currentMonth = currentDate.getMonth()+1;

考虑到当月份是 1 月 (1),日期前 3 个月是 10 月 (10),你们能否为我提供计算和形成日期(Date 数据类型的对象)的逻辑?

【问题讨论】:

    标签: javascript date


    【解决方案1】:
    var d = new Date();
    d.setMonth(d.getMonth() - 3);
    

    这适用于一月份。运行这个 sn-p:

    var d = new Date("January 14, 2012");
    console.log(d.toLocaleDateString());
    d.setMonth(d.getMonth() - 3);
    console.log(d.toLocaleDateString());

    有一些注意事项...

    一个月是一件很奇怪的事情。 1个月怎么定义? 30天?大多数人会说一个月前是指上个月的同一天citation needed。但超过一半的时间,即 31 天前,而不是 30 天。如果今天是本月的 31 日(不是 8 月或 12 月),则上个月中不存在该月的这一天。

    有趣的是,如果你问它what day is one month before another day,Google 会同意 JavaScript:

    它还说one month is 30.4167 days long

    那么,3 月 31 日之前的一个月是否与 3 月 28 日之前的一个月、3 天之前的同一天?这一切都取决于您所说的“一个月前”是什么意思。去和你的产品负责人谈谈吧。

    如果你想像 momentjs 那样做,并通过移动到当月的最后一天来纠正这些最后一天的错误,你可以这样做:

    const d = new Date("March 31, 2019");
    console.log(d.toLocaleDateString());
    const month = d.getMonth();
    d.setMonth(d.getMonth() - 1);
    while (d.getMonth() === month) {
        d.setDate(d.getDate() - 1);
    }
    console.log(d.toLocaleDateString());

    如果您的要求比这更复杂,请使用一些数学运算并编写一些代码。你是开发者!您不必安装库!您不必从 stackoverflow 复制和粘贴!你可以自己开发代码来做你需要的!

    【讨论】:

    • var currentDate = new Date(); var currentMonth = currentDate.getMonth() -12; var pastDate = new Date(2011, currentMonth, 01);警报(过去日期);这行得通,检查了 12 个月
    • 这是一个病态的答案...我要从哪里得到 2012,0,15?转换现有月份 -1 ?
    • @AlexG - 如果您是 JavaScript 日期解析的新手,那么我可以看到我的快速示例是多么令人困惑。 JavaScript 将月份表示为从零开始,其中一月为零。为了避免这种混淆,特别是因为这与问题或我的答案无关,我更新了我的演示以从字符串中获取日期,这应该更直观。
    • 我知道这是旧的,但如果日期是 3 月 31 日,并且您使用这种方法减去一个月,结果就是 3 月 2 日。 jsfiddle.net/atamata/rvumf7dg
    • @atamata - 是的,这很奇怪,但可以预测和预期。 3 月的上个月结束后 31 天是 3 月 31 日,但 2 月是 3 月 2 日。如果要从月底开始计算,则必须为此编写一些自定义代码。
    【解决方案2】:

    一个“单行”(多行以便于阅读))直接放入变量中:

    var oneMonthAgo = new Date(
        new Date().getFullYear(),
        new Date().getMonth() - 1, 
        new Date().getDate()
    );
    

    【讨论】:

    • 不错!不确定它是否适用于所有场景,但似乎工作得很好。
    【解决方案3】:

    我建议使用名为 Moment.js 的库。

    它经过了很好的测试,可以跨浏览器和服务器端工作(我在 Angular 和 Node 项目中都使用它)。它对语言环境日期有很好的支持。

    http://momentjs.com/

    var threeMonthsAgo = moment().subtract(3, 'months');
    
    console.log(threeMonthsAgo.format()); // 2015-10-13T09:37:35+02:00
    

    .format() 返回格式为ISO 8601 格式的日期的字符串表示形式。您还可以将其与自定义日期格式一起使用,如下所示:.format('dddd, MMMM Do YYYY, h:mm:ss a')

    【讨论】:

    【解决方案4】:

    这样做

     let currentdate = new Date();
     let last3months = new Date(currentdate.setMonth(currentdate.getMonth()-3));
    

    Javascript 的setMonth 方法也负责这一年。例如,如果 currentDate 设置为new Date("2020-01-29"),上述代码将返回2020-01-29

    【讨论】:

    • currentdate.setMonth() 的调用更改了currentdate,因此无需基于currentdatelast3months 分配给新的Date。此外,currentdate 不再是“当前日期”。只是在使用此解决方案时要牢记的注意事项。 :)
    • 是的,它是按引用调用的,会改变 currentdate 变量
    【解决方案5】:

    我喜欢gilly3's answer的简洁,但用户可能会惊讶于3月31日之前的一个月是3月3日。我选择实现一个坚持到月底的版本,所以在3月28日之前的一个月,如果不是闰年,29、30 和 31 日都将是 2 月 28 日。

    function addMonths(date, months) {
      var result = new Date(date),
          expectedMonth = ((date.getMonth() + months) % 12 + 12) % 12;
      result.setMonth(result.getMonth() + months);
      if (result.getMonth() !== expectedMonth) {
        result.setDate(0);
      }
      return result;
    }
    
    var dt2004_05_31 = new Date("2004-05-31 0:00"),
        dt2001_05_31 = new Date("2001-05-31 0:00"),
        dt2001_03_31 = new Date("2001-03-31 0:00"),
        dt2001_02_28 = new Date("2001-02-28 0:00"),
        result = addMonths(dt2001_05_31, -2);
    console.assert(dt2001_03_31.getTime() == result.getTime(), result.toDateString());
    
    result = addMonths(dt2001_05_31, -3);
    console.assert(dt2001_02_28.getTime() == result.getTime(), result.toDateString());
    
    result = addMonths(dt2001_05_31, 36);
    console.assert(dt2004_05_31.getTime() == result.getTime(), result.toDateString());
    
    result = addMonths(dt2004_05_31, -38);
    console.assert(dt2001_03_31.getTime() == result.getTime(), result.toDateString());
    
    console.log('Done.');

    【讨论】:

      【解决方案6】:

      因为我似乎没有看到它已经建议......

      const d = new Date();
      const day = d.getDate();
      const goBack = 3;
      for (let i = 0; i < goBack; i++) d.setDate(0);
      d.setDate(day);
      

      这将为您提供 3 个月前的今天日​​期,因为 .setDate(0) 将日期设置为上个月的最后一天,无论一个月包含多少天。 day 用于恢复今天的日期值。

      【讨论】:

        【解决方案7】:

        var d = new Date("2013/01/01");
        console.log(d.toLocaleDateString());
        d.setMonth(d.getMonth() + 18);
        console.log(d.toLocaleDateString());

        【讨论】:

          【解决方案8】:

          如果 gilly3 提供的 setMonth 方法不是您想要的,请考虑:

          var someDate = new Date(); // add arguments as needed
          someDate.setTime(someDate.getTime() - 3*28*24*60*60);
          // assumes the definition of "one month" to be "four weeks".
          

          可以使用任意时间,只需设置正确的倍数。

          【讨论】:

          • 我会选择 gilly3 的回答。你的假设是每月固定的秒数。 JavaScript 的宽松日期算法将保持日期正确。 9 月 28 日之前的三个月应该是 7 月 28 日。
          • 我想知道 JavaScript 会计算出 3 月 31 日减去 1 个月的时间。
          • 在这种情况下,您确实会得到 3 月 3 日(对于 2011 年),因为这就是 2 月 31 日处于宽松模式的时间。但是减去 2 个月,您将得到 1 月 31 日。在每月 28 天的模型下,您不会。尽管 Date 类很弱,并且尽管 Date.js 是首选,但它至少模拟了一个宽松的预测日历,足以满足休闲使用。
          • 你不应该多秒到1000才能正确setTime()吗?
          【解决方案9】:

          这应该处理加法/减法,只需输入一个负值进行减法和一个正值进行加法。这也解决了月份交叉问题。

          function monthAdd(date, month) {
              var temp = date;
              temp = new Date(date.getFullYear(), date.getMonth(), 1);
              temp.setMonth(temp.getMonth() + (month + 1));
              temp.setDate(temp.getDate() - 1); 
          
              if (date.getDate() < temp.getDate()) { 
                  temp.setDate(date.getDate()); 
              }
          
              return temp;    
          }
          

          【讨论】:

            【解决方案10】:

            已经有一个优雅的答案,但我发现它很难阅读,所以我制作了自己的函数。出于我的目的,我不需要否定结果,但修改起来并不难。

                var subtractMonths = function (date1,date2) {
                    if (date1-date2 <=0) {
                        return 0;
                    }
                    var monthCount = 0;
                    while (date1 > date2){
                        monthCount++;
                        date1.setMonth(date1.getMonth() -1);
                    }
                    return monthCount;
                }
            

            【讨论】:

              【解决方案11】:

              为了让事情变得非常简单,你可以使用 DateJS,一个用于 JavaScript 的日期库:

              http://www.datejs.com/

              给你的示例代码:

              Date.today().add({ months: -1 });
              

              【讨论】:

                【解决方案12】:

                就我而言,我需要从当前日期减去 1 个月。重要的部分是月份数,所以它不关心你在当前月份的哪一天,我需要上个月。这是我的代码:

                var dateObj = new Date('2017-03-30 00:00:00'); //Create new date object
                console.log(dateObj); // Thu Mar 30 2017 00:00:00 GMT-0300 (ART)
                
                dateObj.setDate(1); //Set first day of the month from current date
                dateObj.setDate(-1); // Substract 1 day to the first day of the month
                
                //Now, you are in the last month
                console.log(dateObj); // Mon Feb 27 2017 00:00:00 GMT-0300 (ART)
                

                从实际日期减去 1 个月是不准确的,这就是为什么我首先设置当月的第一天(任何一个月的第一天总是第一天),然后我减去 1 天,这总是将您发送到上个月。 希望能帮到你。

                var dateObj = new Date('2017-03-30 00:00:00'); //Create new date object
                console.log(dateObj); // Thu Mar 30 2017 00:00:00 GMT-0300 (ART)
                
                dateObj.setDate(1); //Set first day of the month from current date
                dateObj.setDate(-1); // Substract 1 day to the first day of the month
                
                //Now, you are in the last month
                console.log(dateObj); // Mon Feb 27 2017 00:00:00 GMT-0300 (ART)

                【讨论】:

                  【解决方案13】:

                     
                  
                   var date=document.getElementById("date");
                      var d = new Date();
                     document.write(d + "<br/>");
                      d.setMonth(d.getMonth() - 6);
                      document.write(d);
                  
                   if(d<date)
                    document.write("lesser then 6 months");
                  else
                    document.write("greater then 6 months");

                  【讨论】:

                    【解决方案14】:

                    传递一个 JS Date 对象和一个整数,表示要加/减多少个月。 monthsToAdd 可以是正数或负数。返回一个 JS 日期对象。

                    如果您的 originalDateObject 是 3 月 31 日,并且您将 -1 传递为 monthsToAdd,那么您的输出日期将为 2 月 28 日。

                    如果您经过大量月份,例如 36 个月,它也会正确处理年份调整。

                    const addMonthsToDate = (originalDateObject, monthsToAdd) => {
                      const originalDay = originalDateObject.getUTCDate();
                      const originalMonth = originalDateObject.getUTCMonth();
                      const originalYear = originalDateObject.getUTCFullYear();
                    
                      const monthDayCountMap = {
                        "0": 31,
                        "1": 28,
                        "2": 31,
                        "3": 30,
                        "4": 31,
                        "5": 30,
                        "6": 31,
                        "7": 31,
                        "8": 30,
                        "9": 31,
                        "10": 30,
                        "11": 31
                      };
                    
                      let newMonth;
                      if (newMonth > -1) {
                        newMonth = (((originalMonth + monthsToAdd) % 12)).toString();
                      } else {
                        const delta = (monthsToAdd * -1) % 12;
                        newMonth = originalMonth - delta < 0 ? (12+originalMonth) - delta : originalMonth - delta;
                      }
                    
                      let newDay;
                    
                      if (originalDay > monthDayCountMap[newMonth]) {
                        newDay = monthDayCountMap[newMonth].toString();
                      } else {
                        newDay = originalDay.toString();
                      }
                    
                      newMonth = (+newMonth + 1).toString();
                    
                      if (newMonth.length === 1) {
                        newMonth = '0' + newMonth;
                      }
                    
                      if (newDay.length === 1) {
                        newDay = '0' + newDay;
                      }
                    
                      if (monthsToAdd <= 0) {
                        monthsToAdd -= 11;
                      }
                    
                      let newYear = (~~((originalMonth + monthsToAdd) / 12)) + originalYear;
                    
                      let newTime = originalDateObject.toISOString().slice(10, 24);
                    
                      const newDateISOString = `${newYear}-${newMonth}-${newDay}${newTime}`;
                    
                      return new Date(newDateISOString);
                    };
                    

                    【讨论】:

                      【解决方案15】:

                      var d = new Date();
                      document.write(d + "<br/>");
                      d.setMonth(d.getMonth() - 6);
                      document.write(d);

                      【讨论】:

                        【解决方案16】:

                        这是最小和最简单的代码。

                           var minDate = new Date(); 
                           minDate.setMonth(minDate.getMonth() - 3);
                        

                        声明具有当前日期的变量。 然后只需使用 setMonth 内置函数,我们就可以获得 3 个月的回溯日期。

                        【讨论】:

                        • 为什么是“minDate”?
                        • 只是一个变量名
                        【解决方案17】:
                        Following code give me Just Previous Month From Current Month even the date is 31/30 of current date and last month is 30/29/28 days:
                        
                           <!DOCTYPE html>
                        <html>
                        <body>
                        
                        <p>Click the button to display the date after changing the month.</p>
                        
                        <button onclick="myFunction()">Try it</button>
                        
                        <p id="demo"></p>
                        
                        <script>
                        function myFunction() {
                        
                        var d = new Date("March 29, 2017"); // Please Try the result also for "March 31, 2017" Or "March 30, 2017"
                        var OneMonthBefore =new Date(d);
                        
                        OneMonthBefore.setMonth(d.getMonth(),0);
                        if(OneMonthBefore.getDate() < d.getDate()  )
                        {
                        d.setMonth(d.getMonth(),0);
                        }else
                        {
                        d.setMonth(d.getMonth()-1);
                        
                        }
                        
                            document.getElementById("demo").innerHTML = d;
                        }
                        </script>
                        
                        </body>
                        </html>
                        

                        【讨论】:

                        • 这个答案与已经存在的其他 7 个相当古老的答案有何不同?
                        【解决方案18】:

                        d.setMonth 在浏览器尝试更改本地时间

                         const calcDate = (m) => {
                            let date = new Date();
                            let day = date.getDate();
                            let month = date.getMonth() + 1;
                            let year = date.getFullYear();
                            let days = 0;
                        
                            if (m > 0) {
                              for (let i = 1; i < m; i++) {
                                month += 1;
                                if (month > 12) {
                                  year += 1;
                                  month = 1;
                                }
                                days += new Date(year, month, 0).getDate();
                              }
                            } else {
                              for (let i = m; i < 0; i++) {
                                month -= 1;
                                if (month < 1) {
                                  year -= 1;
                                  month = 12;
                                }
                                days -= new Date(year, month, 0).getDate();
                              }
                            }
                        
                            const newTime = date.getTime() + 3600 * 24 * 1000 * days;
                            return new Date(newTime);
                          };
                        
                        calcDate(3)//+3 month
                        

                        【讨论】:

                          【解决方案19】:

                          var todayDate = new Date().toISOString().slice(0, 10);
                          var d = new Date(todayDate);
                          d.setMonth(d.getMonth() -3);
                          console.log(todayDate)
                          console.log(d.toISOString().slice(0, 10));

                          【讨论】:

                            【解决方案20】:

                            由于“2 月 31 日”会自动转换为“3 月 3 日”或“3 月 2 日”,因此比“3 月 31 日”早一个月,这很违反直觉,我决定按照我的想法去做. 与@Don Kirkby 的回答类似,我还将日期修改为目标月份的最后一天。

                            function nMonthsAgo(date, n) {
                              // get the target year, month, date
                              const y = date.getFullYear() - Math.trunc(n / 12) 
                              const m = date.getMonth() - n % 12
                              let d = date.getDate()
                              if (d > 27) {   // get a valid date
                                const lastDateofMonth = new Date(y, m + 1, 0).getDate()
                                d = Math.min(d, lastDateofMonth) 
                              }
                              return new Date(y, m, d) 
                            }
                            
                            d = new Date('2022-03-31')
                            nMonthsAgo(d, 1).toLocaleDateString()
                            

                            最后,我喜欢@gilly3 在他的回答中所说的话:

                            如果您的要求比这更复杂,请使用一些数学运算并编写一些代码。你是开发者!您不必安装库!您不必从 stackoverflow 复制和粘贴!你可以自己开发代码来做你需要的!

                            【讨论】:

                              【解决方案21】:

                              for (let monthOfYear = 0; monthOfYear < 12; monthOfYear++) {
                                const maxDate = new Date();
                                const minDate = new Date();
                                const max = maxDate.setMonth(maxDate.getMonth() - (monthOfYear - 1), 0);
                                const min = maxDate.setMonth(minDate.getMonth() - (monthOfYear), 1);
                              
                                console.log('max: ', new Date(max));
                                console.log('min: ', new Date(min));
                              }

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2019-12-13
                                • 2017-07-17
                                • 1970-01-01
                                • 2011-05-08
                                相关资源
                                最近更新 更多