如何在同一天找到上个月的纪元?

时间:2016-10-13 09:54:44

标签: sql oracle plsql oracle11g epoch

我有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;

e.g。如果今天的日期是,

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

1 个答案:

答案 0 :(得分:0)

也许这样的事情会成功吗?

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进行比较并选择最低值。因此,对于九月,如果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 

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

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