【问题标题】:How to find epoch for last month same day?如何找到上个月同一天的纪元?
【发布时间】:2017-02-22 09:19:48
【问题描述】:

我有以下 PLSQL 代码,可以找到上个月同一天的纪元,但是当我在月底运行 31 天和 01 天时它失败了。

 SET serveroutput ON
    DECLARE
      vDay        VARCHAR2(30) := '&Enter_current_day';
      vDate        VARCHAR2(30);
      vEpoch       NUMBER;
    BEGIN
      vDate  := TO_CHAR(sysdate, 'MM')||'-'||vDay||'-'||TO_CHAR(sysdate, 'YYYY');
      vEpoch := (ADD_MONTHS(TO_DATE(vDate, 'MM-DD-YYYY HH24:MI:SS'), -1) - TO_DATE('01/01/1970 00:00:00', 'MM-DD-YYYY HH24:MI:SS')) * 24 * 60 * 60;
      vDate  := TO_DATE(vDate, 'MM-DD-YYYY HH24:MI:SS');
      dbms_output.put_line('Current Date: '||to_number(vDay)||' Epoch: '||vEpoch||' Date: '||vDate);
    END;

例如如果是今天,

A. 30-Sep and if I enter '31' then it should return epoch for the 01-Sep
B. 30-Sep and if I enter '01' then it should return epoch for the 01-Sep
C. 30-Mar and if I enter '31' then it should return epoch for the 01-Mar
D. 30-Mar and if I enter '01' then it should return epoch for the 01-Mar

【问题讨论】:

  • 对于案例 B 和 D,您真的想要当月的第一天吗?不应该是这个月的最后一天吗?

标签: sql oracle plsql oracle11g epoch


【解决方案1】:

也许这样的事情可以解决问题?

DECLARE
  vday    VARCHAR2(30) := '&Enter_current_day';
  vdate   DATE;
  vepoch  NUMBER;
  v_today DATE := SYSDATE - 30;
BEGIN
  vdate  := to_date(to_char(v_today, 'MM') || '-' ||
                      least(to_number(vday),
                      to_number(to_char(last_day(v_today), 'dd'))) || '-' ||
                      to_char(v_today, 'YYYY'),
                    'MM-DD-YYYY');
  vepoch := (add_months(vdate, -1) -
               to_date('01/01/1970 00:00:00', 'MM-DD-YYYY HH24:MI:SS')) * 24 * 60 * 60;

  dbms_output.put_line('Current Date: ' || to_number(vday) || ' Epoch: ' ||
                 vepoch || ' Date: ' || to_char(vdate, 'mm-dd-yyyy'));
END;

Current Date: 1 Epoch: 1470009600 Date: 09-01-2016
Current Date: 15 Epoch: 1471219200 Date: 09-15-2016
Current Date: 30 Epoch: 1472601600 Date: 09-30-2016
Current Date: 31 Epoch: 1472601600 Date: 09-30-2016

这只是查找v_today 日期返回的月份的最后一天,并将其与输入vday 进行比较并选择最小值。因此,对于 9 月,如果 vday = 31,它将比较 31 和 30(9 月的最后一天)并输出 30。

如果您对返回当月的第一天一无所知,那么您需要将 least 部分更改为:

CASE WHEN to_number(to_char(last_day(v_today), 'dd')) < to_number(vday)
          THEN '01'
     ELSE vday
END 

注意请注意,我对您的代码进行了一些更改以使其更加健壮 - 例如。你有 vDate := TO_DATE(vDate, 'MM-DD-YYYY HH24:MI:SS'); 这有点愚蠢,因为你最初将 vDate 作为一个字符串,并且通过这样做,你迫使 Oracle 将字符串隐式转换为日期,然后再转换回字符串。

相反,我将vDate 声明为日期,并以您在其余代码中使用的日期格式输出结果字符串中的日期 - 这意味着它不再依赖 NLS nls_date_format 参数来决定(这个参数不一定每个人都一样!)。

【讨论】:

    猜你喜欢
    • 2020-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-03
    • 2022-11-25
    • 1970-01-01
    • 2020-04-08
    • 2018-11-24
    相关资源
    最近更新 更多