Создание интервала дат из одиночной даты
Иногда у интервалов времени нет четко выраженного начала и конца. Они подразумеваются только одним полем — меткой времени изменения.
Это может быть как в таблице ниже, где для различных валют указаны курсы валют. Каждый курс валют указан в отдельной строке, каждый — с новым обменным курсом. Также в таблице есть строки с пустыми датами, соответствующими исходному обменному курсу, который существовал до первого изменения.
Валюта | Дата изменения | Курс |
---|---|---|
EUR | - | 8.59 |
EUR | 28/01/2013 | 8.69 |
EUR | 15/02/2013 | 8.45 |
USD | - | 6.50 |
USD | 10/01/2013 | 6.56 |
USD | 03/02/2013 | 6.30 |
Таблица выше определяет набор неперекрывающихся интервалов, где дата начала называется Change Date, а дата конца определяется началом следующего интервала. Но поскольку дата конца хранится в своем столбце неявно, необходимо создать такой столбец, чтобы новая таблица стала списком интервалов.
Выполните следующие действия.
- Создайте новое приложение и дайте ему имя.
- Добавьте новый раздел скрипта в Редакторе загрузки данных.
- Добавьте следующую встроенную таблицу. Убедитесь, что даты в столбце Change Date указаны в локальном формате дат.
-
Определите временной диапазон, с которым вы хотели бы работать. Начало диапазона должно предшествовать первой дате в данных, а конец диапазона должен быть после последней даты.
Добавьте следующую запись в начало скрипта:
Let vBeginTime = Num('1/1/2013'); Let vEndTime = Num('1/3/2013'); Let vEpsilon = Pow(2,-27);
-
Загрузите исходные данные, но измените пустые даты на начало диапазона, определенного в предыдущем маркере. Дата изменения должна быть загружена как "From Date".
Отсортируйте таблицу сначала по элементу Currency, а затем по элементу "From Date" в убывающем порядке, так чтобы последние даты оказались сверху.
После таблицы In_Rates добавьте следующее:
Tmp_Rates: LOAD Currency, Rate, Date(If(IsNum([Change Date]), [Change Date], $(#vBeginTime))) as FromDate Resident In_Rates;
-
Еще раз пройдитесь по данным, где вычисляется элемент "To Date". Если валюта текущей записи отличается от валюты предыдущей, то это первая запись новой валюты (но ее последнего интервала), поэтому следует использовать конец диапазона, определенного в шаге 1. Если это та же валюта, возьмите элемент "From Date" из предыдущей записи, вычтите небольшое количество времени и используйте это значение в текущей записи как элемент "To Date".
После таблицы Tmp_Rates добавьте следующее:
Rates: LOAD Currency, Rate, FromDate, Date(If( Currency=Peek('Currency'), Peek('FromDate') - $(#vEpsilon), $(#vEndTime) )) as ToDate Resident Tmp_Rates Order By Currency, FromDate Desc; Drop Table Tmp_Rates;
In_Rates:
LOAD * Inline [
Currency,Change Date,Rate
EUR,,8.59
EUR,28/01/2013,8.69
EUR,15/02/2013,8.45
USD,,6.50
USD,10/01/2013,6.56
USD,03/02/2013,6.30
];
Скрипт должен выглядеть следующим образом:
Let vBeginTime = Num('1/1/2013');
Let vEndTime = Num('1/3/2013');
Let vEpsilon = Pow(2,-27);
In_Rates:
LOAD * Inline [
Currency,Change Date,Rate
EUR,,8.59
EUR,28/01/2013,8.69
EUR,15/02/2013,8.45
USD,,6.50
USD,10/01/2013,6.56
USD,03/02/2013,6.30
];
Tmp_Rates:
LOAD Currency, Rate,
Date(If(IsNum([Change Date]), [Change Date], $(#vBeginTime))) as FromDate
Resident In_Rates;
Rates:
LOAD Currency, Rate, FromDate,
Date(If( Currency=Peek('Currency'),
Peek('FromDate') - $(#vEpsilon),
$(#vEndTime)
)) as ToDate
Resident Tmp_Rates
Order By Currency, FromDate Desc;
Drop Table Tmp_Rates;
Скрипт обновит исходную таблицу следующим образом:
Валюта | Курс | FromDate | ToDate |
---|---|---|---|
EUR | 8.45 | 15/02/2013 | vEndTime |
EUR | 8.69 | 28/01/2013 | 14/02/2013 23:59:59 |
EUR | 8.59 | vBeginTime | 28/01/2013 23:59:99 |
USD | 6.30 | 03/02/2013 | vEndTime |
USD | 6.56 | 10/01/2013 | 2/02/2013 23:59:59 |
USD | 6.50 | vBeginTime | 9/01/2013 23:59:59 |
В приложении таблица отобразится в следующем виде:
Валюта | Курс | FromDate | ToDate |
---|---|---|---|
EUR | 8.45 | 15/02/2013 | 01/03/2013 |
EUR | 8.69 | 28/01/2013 | 14/02/2013 |
EUR | 8.59 | 01/01/2013 | 28/01/2013 |
USD | 6.30 | 03/02/2013 | 01/03/2013 |
USD | 6.56 | 10/01/2013 | 2/02/2013 |
USD | 6.50 | 01/01/2013 | 9/01/2013 |
Впоследствии эту таблицу можно использовать при сравнении с существующей датой с помощью способа Intervalmatch.