我想要计算2个日期时间字段之间的月数。

有没有比获取unix时间戳和除以2 592 000(秒)更好的方法并在MySQL中进行舍入?

有帮助吗?

解决方案

DATEDIFF 函数可以给你两个日期之间的天数。哪个更准确,因为......你怎么定义一个月? (28,29,30或31天?)

其他提示

任何给定的两个日期之间的月差异:

我很惊讶尚未提及:

查看 < MySQL中的strong> TIMESTAMPDIFF() 功能。

这允许你做的是传入两个TIMESTAMPDATETIME值(甚至DATE,因为MySQL将自动转换)以及你想要根据你的差异所用的时间单位。

您可以在第一个参数中指定MONTH作为单位:

SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-04')
-- Outputs: 0

SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-05')
-- Outputs: 1

SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-15')
-- Outputs: 1

SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-12-16')
-- Outputs: 7

它基本上获取参数列表中从第一个日期开始经过的月数。该解决方案可自动补偿每月不同的天数(28,30,31)以及考虑闰年<!>#8212;你不必担心任何这些东西。


精确的月差:

如果你想在经过的月数中引入小数精度,这会有点复杂,但是你可以这样做:

SELECT 
  TIMESTAMPDIFF(MONTH, startdate, enddate) +
  DATEDIFF(
    enddate,
    startdate + INTERVAL
      TIMESTAMPDIFF(MONTH, startdate, enddate)
    MONTH
  ) /
  DATEDIFF(
    startdate + INTERVAL
      TIMESTAMPDIFF(MONTH, startdate, enddate) + 1
    MONTH,
    startdate + INTERVAL
      TIMESTAMPDIFF(MONTH, startdate, enddate)
    MONTH
  )

其中startdateenddate是您的日期参数,无论是来自表中的两个日期列还是来自脚本的输入参数:

示例:

With startdate = '2012-05-05' AND enddate = '2012-05-27':
-- Outputs: 0.7097

With startdate = '2012-05-05' AND enddate = '2012-06-13':
-- Outputs: 1.2667

With startdate = '2012-02-27' AND enddate = '2012-06-02':
-- Outputs: 3.1935

PERIOD_DIFF 计算两个日期之间的月份。

例如,要计算your_table中的now()和时间列之间的差异:

select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;

我也使用 PERIODDIFF 。要获取日期的年份和月份,我使用函数 EXTRACT

  SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;

我更喜欢这种方式,因为每个人都会在第一眼就清楚地理解它:

SELECT
    12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
    tab;

正如这里的许多答案所示,“正确”的答案取决于你所需要的。在我的情况下,我需要舍入到最接近的整数

考虑以下示例: 1月1日 - <!> gt; 1月31日:整整0个月,差不多1个月。 1月1日 - <!> gt; 2月1日?它整整一个月,恰好是一个月。

要获得整个(完整)个月的数量,请使用:

SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31');  => 0
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01');  => 1

要在几个月内获得舍入持续时间,您可以使用:

SELECT ROUND(TIMESTAMPDIFF(DAY, '2018-01-01', '2018-01-31')*12/365.24); => 1
SELECT ROUND(TIMESTAMPDIFF(DAY, '2018-01-01', '2018-01-31')*12/365.24); => 1

准确度为+/- 5天,范围超过1000年。 Zane的答案显然更准确,但我的喜好太过冗长。

来自MySQL手册:

  

PERIOD_DIFF(P1,P2)

     

返回期间P1和P2之间的月数。 P1和P2的格式应为YYMM或YYYYMM。请注意,句点参数P1和P2不是日期值。

     

MySQL的GT <!>; SELECT PERIOD_DIFF(200802,200703);            - GT <!>; 11

所以有可能做这样的事情:

Select period_diff(concat(year(d1),if(month(d1)<10,'0',''),month(d1)), concat(year(d2),if(month(d2)<10,'0',''),month(d2))) as months from your_table;

其中d1和d2是日期表达式。

我必须使用if()语句来确保月份是一个两位数的数字,如02而不是2.

有更好的方法吗? 是。不要使用MySQL时间戳。除了它们占用36个字节之外,它们根本不方便使用。 我建议使用朱利安日期和午夜的所有日期/时间值。 这些可以组合成一个UnixDateTime。如果它存储在DWORD(无符号4字节整数)中,那么自从epoc,01/01/1970以来,直到2106的日期可以存储为秒。 DWORD max val = 4,294,967,295 - DWORD可以保存136年的秒数

Julian Dates非常适合在进行日期计算时使用 在进行日期/时间计算时,UNIXDateTime值可以使用 这两个都不好看,所以当我需要一个我不会做太多计算的专栏时,我会使用时间戳,但我想要一目了然的指示。

转换为Julian并返回可以用一种好的语言很快完成。使用指针我将它降低到大约900个Clks(当然这也是从STRING到INTEGER的转换)

当您进入使用日期/时间信息的严肃应用程序时,例如金融市场,Julian日期是事实上的。

查询将如下:

select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..

从客户记录中创建的日期戳开始,给出了许多日历月,让MySQL在内部进行月份选择。

DROP FUNCTION IF EXISTS `calcula_edad` $$
CREATE DEFINER=`root`@`localhost` FUNCTION `calcula_edad`(pFecha1 date, pFecha2 date, pTipo char(1)) RETURNS int(11)
Begin

  Declare vMeses int;
  Declare vEdad int;

  Set vMeses = period_diff( date_format( pFecha1, '%Y%m' ), date_format( pFecha2, '%Y%m' ) ) ;

  /* Si el dia de la fecha1 es menor al dia de fecha2, restar 1 mes */
  if day(pFecha1) < day(pFecha2) then
    Set vMeses = VMeses - 1;
  end if;

  if pTipo='A' then
    Set vEdad = vMeses div 12 ;
  else
    Set vEdad = vMeses ;
  end if ;
  Return vEdad;
End

select calcula_edad(curdate(),born_date,'M') --  for number of months between 2 dates

执行此代码,它将创建一个函数datedeifference,它将为您提供日期格式yyyy-mm-dd的差异。

DELIMITER $$

CREATE FUNCTION datedifference(date1 DATE, date2 DATE) RETURNS DATE
NO SQL

BEGIN
    DECLARE dif DATE;
    IF DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2)))) < 0    THEN
                SET dif=DATE_FORMAT(
                                        CONCAT(
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 , 
                                            '-',
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 , 
                                            '-',
                                            DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(DATE_SUB(date1, INTERVAL 1 MONTH)), '-', DAY(date2))))),
                                        '%Y-%m-%d');
    ELSEIF DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2)))) < DAY(LAST_DAY(DATE_SUB(date1, INTERVAL 1 MONTH))) THEN
                SET dif=DATE_FORMAT(
                                        CONCAT(
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 , 
                                            '-',
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 , 
                                            '-',
                                            DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2))))),
                                        '%Y-%m-%d');
    ELSE
                SET dif=DATE_FORMAT(
                                        CONCAT(
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 , 
                                            '-',
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 , 
                                            '-',
                                            DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2))))),
                                        '%Y-%m-%d');
    END IF;

RETURN dif;
END $$
DELIMITER;

这取决于您希望如何定义月数。回答这个问题:'月份有什么不同:2008年2月15日 - 2009年3月12日'。它是由明确的天数来定义的,这取决于闰年 - 它是月份,还是上个月的同一天= 1个月。

天数计算

2月15日 - <!> gt; 29(闰年)= 14 2008年3月1日+ 365 = 2009年3月1日。 3月1日 - <!> gt; 3月12日= 12天。 14 + 365 + 12 = 391天。 总计= 391天/(平均每月= 30)= 13.03333

计算月数

2008年2月15日 - 2009年2月15日= 12 2月15日 - <!> gt; 3月12日=不到1个月 总计= 12个月,如果15日 - 12月12日被视为“过去一个月”,则为13个月

SELECT * 
FROM emp_salaryrevise_view 
WHERE curr_year Between '2008' AND '2009' 
    AND MNTH Between '12' AND '1'

我需要精确的月差。虽然Zane Bien的解决方案是正确的,但他的第二个和第三个例子给出了不准确的结果。 2月份的一天除以2月份的天数不等于5月份的天数除以5月份的天数。所以第二个例子应该输出((31-5 + 1)/ 31 + 13/30 =)1.3043和第三个例子((29-27 + 1)/ 29 + 2/30 + 3 =)3.1701。

我最终得到了以下查询:

SELECT
    '2012-02-27' AS startdate,
    '2012-06-02' AS enddate,
    TIMESTAMPDIFF(DAY, (SELECT startdate), (SELECT enddate)) AS days,
    IF(MONTH((SELECT startdate)) = MONTH((SELECT enddate)), 0, (TIMESTAMPDIFF(DAY, (SELECT startdate), LAST_DAY((SELECT startdate)) + INTERVAL 1 DAY)) / DAY(LAST_DAY((SELECT startdate)))) AS period1,     
    TIMESTAMPDIFF(MONTH, LAST_DAY((SELECT startdate)) + INTERVAL 1 DAY, LAST_DAY((SELECT enddate))) AS period2,
    IF(MONTH((SELECT startdate)) = MONTH((SELECT enddate)), (SELECT days), DAY((SELECT enddate))) / DAY(LAST_DAY((SELECT enddate))) AS period3,
    (SELECT period1) + (SELECT period2) + (SELECT period3) AS months

您可以通过这种方式获得年,月和日:

SELECT 
username
,date_of_birth
,DATE_FORMAT(CURDATE(), '%Y') - DATE_FORMAT(date_of_birth, '%Y') - (DATE_FORMAT(CURDATE(), '00-%m-%d') < DATE_FORMAT(date_of_birth, '00-%m-%d')) AS years
,PERIOD_DIFF( DATE_FORMAT(CURDATE(), '%Y%m') , DATE_FORMAT(date_of_birth, '%Y%m') ) AS months
,DATEDIFF(CURDATE(),date_of_birth) AS days
FROM users

你也可以试试这个:

select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name;

OR

select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name;

PERIOD_DIFF()函数

其中一种方法是MySQL PERIOD_DIFF()返回两个句点之间的差异。期间应采用相同的格式,即YYYYMM或YYMM。需要注意的是,期间不是日期值。

<强>代码:

SELECT PERIOD_DIFF(200905,200811);

简单回答将开始日期设为ins_frm,将结束日期设为ins_to

SELECT convert(TIMESTAMPDIFF(year, ins_frm, ins_to),UNSIGNED) as yrs,
       mod(TIMESTAMPDIFF(MONTH, ins_frm, ins_to),12) mnths
FROM table_name

享受:)))

试试这个

SELECT YEAR(end_date)*12 + MONTH(end_date) - (YEAR(start_date)*12 + MONTH(start_date))

此查询对我有用:)

SELECT * FROM tbl_purchase_receipt
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'

它只需要两个日期并检索它们之间的值。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top