在4GL中发出计算月结束日期的问题

时间:2016-01-07 14:58:34

标签: sql informix 4gl genero

此例程将于2016年12月31日返回,而不是2015年12月31日,并且会弄乱报告。 知道哪里出错了?

    LET date_month = MONTH(p_selection.date_from)
IF  date_month = 12 THEN 
    LET date_month = 1
    LET p_selection.date_from = p_selection.date_from + 1 UNITS YEAR
    LET date_thru = date_month,"/01/",YEAR(p_selection.date_from)
    LET p_selection.date_from = p_selection.date_from - 1 UNITS YEAR
ELSE 
    LET date_month = date_month + 1
    LET date_thru = date_month,"/01/",YEAR(p_selection.date_from)
END IF

LET p_selection.date_thru = date_thru CLIPPED

IF YEAR(p_selection.date_thru) <> YEAR(p_selection.date_from) THEN 
    LET p_selection.date_thru = p_selection.date_thru + 1 UNITS YEAR
END IF 
    LET p_selection.date_thru = p_selection.date_thru - 1

3 个答案:

答案 0 :(得分:1)

假设输入p_selection.date_from是12/01/2015 ...

IF date_month = 12返回TRUE,因此date_thru计算为01/01/2016

但是第二个IF语句也会返回TRUE,再添加一年到p_selection.date_thru(01/01/2017),然后将其减少一天到2016年12月31日。

在我看来,有人试图计算一个月的最后一天的日期,并且需要一种或另一种方法,而不是两者。在您的代码中首先出现的那个特别可疑 - 假设DBDATE在DATE和CHAR之间转换时是美国格式,这完全没必要。

更简单的解决方案是简单地计算:

LET p_selection.date_thru = 
    MDY(MONTH(p_selection.date_from), 1, YEAR(p_selection.date_from))
    + 1 UNITS MONTH - 1 UNITS DAY

换句话说,找到所选月份的第一天,添加一个月并减去一天。它简单而强大,适用于年界和闰日。

答案 1 :(得分:0)

这里有一些旧的代码,偶尔没有见到,但仍然是有效的I4GL。

ltmonth.4gl

{
    @(#)$Id: ltmonth.4gl,v 1.4 1990/04/05 11:02:05 john Exp $
    @(#)Sphinx Informix Tools: General Library
    @(#)Find last day of this month
    @(#)Author: JL
}

FUNCTION last_of_this_month(edate)

    DEFINE
        edate   DATE        { Effective date (frequently TODAY) }

    IF edate IS NULL THEN
        RETURN edate
    END IF

    RETURN first_of_next_month(edate) - 1

END FUNCTION {last_of_this_month}

fnmonth.4gl

{
    @(#)$Id: fnmonth.4gl,v 1.4 1990/04/05 11:02:03 john Exp $
    @(#)Sphinx Informix Tools: General Library
    @(#)Find 1st of next month
    @(#)Author: JL
}

FUNCTION first_of_next_month(edate)

    DEFINE
        edate   DATE,       { Effective date (frequently TODAY) }
        mm      INTEGER,    { Month number }
        yy      INTEGER     { Year }

    IF edate IS NULL THEN
        RETURN edate
    END IF

    LET mm = MONTH(edate) + 1
    LET yy = YEAR(edate)
    IF mm > 12 THEN
        LET mm = 1
        LET yy = yy + 1
    END IF

    RETURN MDY(mm, 1, yy)

END FUNCTION {first_of_next_month}

lastthismonth.spl

这里有一些基于上述I4GL的SPL:

-- @(#)$Id: lastthismonth.spl,v 1.2 2008/07/20 02:54:37 jleffler Exp $
--
-- @(#)Create last_of_this_month Stored Procedure
--
-- @(#)Version: ltmonth.4gl,v 1.4 1990/04/05 11:02:05 john
-- @(#)Sphinx Informix Tools: General Library
-- @(#)Find last day of this month
-- @(#)Author: JL
--
-- Alternative expression: 
-- (MDY(MONTH(dateval), 1, YEAR(dateval)) + 1 UNITS MONTH) - 1 UNITS DAY

CREATE PROCEDURE last_of_this_month(edate DATE DEFAULT TODAY)
    RETURNING DATE AS last_of_this_month;

    IF edate IS NULL THEN
        RETURN edate;
    END IF

    RETURN first_of_next_month(edate) - 1;

END PROCEDURE {last_of_this_month};

firstnextmonth.spl

-- @(#)$Id: firstnextmonth.spl,v 1.1 2008/07/20 02:21:13 jleffler Exp $
--
-- @(#)Create first_of_next_month Stored Procedure
--
-- @(#)Version: fnmonth.4gl,v 1.4 1990/04/05 11:02:03 john
-- @(#)Sphinx Informix Tools: General Library
-- @(#)Find 1st of next month
-- @(#)Author: JL

CREATE PROCEDURE first_of_next_month(edate DATE DEFAULT TODAY)
    RETURNING INTEGER AS first_of_next_month;

    DEFINE mm   INTEGER;    { Month number }
    DEFINE yy   INTEGER;    { Year }

    IF edate IS NULL THEN
        RETURN edate;
    END IF

    LET mm = MONTH(edate) + 1;
    LET yy = YEAR(edate);
    IF mm > 12 THEN
        LET mm = 1;
        LET yy = yy + 1;
    END IF

    RETURN MDY(mm, 1, yy);

END PROCEDURE {first_of_next_month};

请注意替代表达式。它有效,但它是DATE和DATETIME计算的一个令人难以置信的混合。

答案 2 :(得分:0)

我有

FUNCTION last_of_month(m,y)
DEFINE m,y SMALLINT
    RETURN MDY(m,days_in_month(m,y),y)
END FUNCTION

使用适当的函数days_in_month()根据月份和年份适当返回28,29,30,31

对于OP,你应该创建一个函数并重新使用它,而不是像你看起来那样重复逻辑。

我真正想评论的是,在Genero,我们正在讨论添加内置函数来进行这些类型的计算。如果每个人都有自己的first_of_month,last_of_month,add_months,那么我们应该考虑将它们包含在语言中,而不是让每个人重新发明轮子。作为讨论的一部分,我学到的是在他的回答中使用的+ 1个单位月,就像他说闰年安全一样。出于某种原因,我认为它不是,并且倾向于避免它,并以JLefflers的答案写出来。看看我见过的其他4GL / Genero客户库代码,我怀疑其他开发人员也有同样的想法。