Используйте MultiIndex.from_arrays
с PeriodIndex.year
и PeriodIndex.month
:
idx = pd.PeriodIndex(['2015-01', '2015-02', '2015-03', '2015-04', '2015-05', '2015-06',
'2015-07', '2015-08', '2015-09', '2015-10', '2015-11', '2015-12',
'2016-01', '2016-02', '2016-03', '2016-04', '2016-05', '2016-06',
'2016-07', '2016-08', '2016-09', '2016-10', '2016-11', '2016-12'],
dtype='period[M]', name='DT', freq='M')
mux = pd.MultiIndex.from_arrays([idx.year, idx.month], names=['year','month'])
print (mux)
MultiIndex(levels=[[2015, 2016], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]],
labels=[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]],
names=['year', 'month'])
Мы используем следующие две функции для вычисления запуска и даты окончания на любой данный год (сообщение 2007, США).
Function DaylightSavingTimeStart (p_Date IN Date)
Return Date Is
v_Date Date;
v_LoopIndex Integer;
Begin
--Set the date to the 8th day of March which will effectively skip the first Sunday.
v_Date := to_date('03/08/' || to_char(p_Date,'YYYY') || '02:00:00 AM','MM/DD/YYYY HH:MI:SS PM');
--Advance to the second Sunday.
FOR v_LoopIndex IN 0..6 LOOP
If (RTRIM(to_char(v_Date + v_LoopIndex,'DAY')) = 'SUNDAY') Then
Return v_Date + v_LoopIndex;
End If;
END LOOP;
End;
Function DaylightSavingTimeEnd (p_Date IN Date)
Return Date Is
v_Date Date;
v_LoopIndex Integer;
Begin
--Set Date to the first of November this year
v_Date := to_date('11/01/' || to_char(p_Date,'YYYY') || '02:00:00 AM','MM/DD/YYYY HH:MI:SS PM');
--Advance to the first Sunday
FOR v_LoopIndex IN 0..6 LOOP
If (RTRIM(to_char(v_Date + v_LoopIndex,'DAY')) = 'SUNDAY') Then
Return v_Date + v_LoopIndex;
End If;
END LOOP;
End;
Существует, вероятно, более простой способ сделать это, но они работали на нас. Конечно, этот запрос не знает, наблюдается ли летнее время для того, где Вы. Для этого Вам будут нужны данные местоположения.
В Соединенных Штатах Летнее время определяется как начинающийся во второе воскресенье в марте и заканчивающийся в первое воскресенье в ноябре, для областей, которые наблюдают DST, в течение многих лет после 2007.
Я не думаю, что существует простой способ получить эту информацию от Oracle, но на основе стандартного определения, необходимо смочь записать хранимую процедуру, которая вычисляет начало и конечную дату с помощью Алгоритма Судного дня.
Вот способ использовать Оракулов внутреннее знание того, наблюдает ли часовой пояс летнее время или не определить запуск и конец его. Кроме сложности и общей странности его, он требует, чтобы два часовых пояса, чтобы быть знали, имеют идентичные времена, когда летнее время не в действительности и различные времена, когда это. Как таковой это эластично к изменениям конгресса в том, когда летнее время происходит (предположение, что Ваша база данных актуальна с патчами), но не эластично к региональным изменениям, производящим часовые пояса, выключенные. С теми предупреждениями вот то, что я имею.
ALTER SESSION SET time_zone='America/Phoenix';
DROP TABLE TimeDifferences;
CREATE TABLE TimeDifferences(LocalTimeZone TIMESTAMP(0) WITH LOCAL TIME ZONE);
INSERT INTO TimeDifferences
(
SELECT to_date('01/01/' || to_char(sysdate-365,'YYYY') || '12:00:00','MM/DD/YYYYHH24:MI:SS')+rownum-1
FROM dual CONNECT BY rownum<=365
);
COMMIT;
ALTER SESSION SET time_zone='America/Edmonton';
SELECT LocalTimeZone-1 DaylightSavingTimeStartAndEnd
FROM
(
SELECT LocalTimeZone,
to_char(LocalTimeZone,'HH24') Hour1,
LEAD(to_char(LocalTimeZone,'HH24')) OVER (ORDER BY LocalTimeZone) Hour2
FROM TimeDifferences
)
WHERE Hour1 <> Hour2;
Я сказал Вам, что это было странно. Код только выясняет день изменения, но мог быть улучшен для показа часа. В настоящее время это возвращает 09-MAR-08 и 02-NOV-08. Это также чувствительно ко времени года, это выполняется, который является, почему я должен был сделать-365... +365. В целом, я не рекомендую это решение, но это была забава заняться расследованиями. Возможно, у кого-то еще есть что-то лучше.
Вместо цикла для получения следующего воскресенья вы также можете использовать функцию Oracle next_day (date, 'SUN').