2016-10-13 5 views
0

У меня ниже кода 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 
+0

для случаев B и D, вы действительно хотели первую часть месяца? Разве это не последний день месяца? – Boneist

ответ

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 (последний день сентября) и вывести 30.

Если вы мертвы, вернувшись в первый день месяца, вам понадобится изменить раздел least на что-то вроде:

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

NB Обратите внимание, что я внес несколько изменений в код, чтобы сделать его более надежным - например. У вас был vDate := TO_DATE(vDate, 'MM-DD-YYYY HH24:MI:SS');, который был немного глупым, так как вы изначально имели vDate в качестве строки, и тем самым вы вынуждаете Oracle неявно преобразовывать строку в дату, а затем обратно в строку.

Вместо этого, я объявил vDate как дату и иметь выводим дату в результирующей строке в формате даты, который вы использовали на протяжении всего остального кода - это не означает, что он больше не зависит от параметра NLS nls_date_format решить (этот параметр не обязательно одинаково для всех!).

Смежные вопросы