Introduction

Daru’s (Data Analysis in RUby) latest release (0.2.0) brings in a host of new features, most important among them being time series manipulation functionality. In this post, we will go over the date offsets that daru offers, which can be used for creating date indexes of specific intervals. The offsets offer a host of options for easy creation of different intervals and even work with standalone DateTime objects to increase or decrease time.

Offset classes and behaviour

The date offsets are contained in the Daru::Offsets sub-module. A number of classes are offered, each of which implements business logic for advancing or retracting date times by a specific interval.

To demonstrate with a quick example:


require 'daru'

offset = Daru::Offsets::Hour.new
offset + DateTime.new(2012,4,5,4)
#=> #<DateTime: 2012-04-05T05:00:00+00:00 ((2456023j,18000s,0n),+0s,2299161j)>

As you can see in the above example, an hour was added to the time specified by DateTime and returned. All the offset classes work in a similar manner. Following offset classes are available to users:

Offset Class Description
Daru::DateOffset Generic offset class
Second One Second
Minute One Minute
Hour One Hour
Day One Day
Week One Week. Can be anchored on any week of the day.
Month One Month.
MonthBegin Calendar Month Begin.
MonthEnd Calendar Month End.
Year One Year.
YearBegin Calendar Year Begin.
YearEnd Calendar Year End.

The generic Daru::DateOffset class is used for creating a generic offset by passing the number of intervals you want as the value for a key that describes the type of interval. For example to create an offset of 3 days, you pass the option days: 3 into the Daru::Offset constructor.


require 'daru'

offset = Daru::DateOffset.new(days: 3)
offset + DateTime.new(2012,4,5,2)
#=> #<DateTime: 2012-04-08T02:00:00+00:00 ((2456026j,7200s,0n),+0s,2299161j)>

On a similar note, the DateOffset class constructor can accept the options :secs, :mins,:hours, :days, :weeks, :months or :years. Optionally, specifying the :n option will tell DateOffset to apply a particular offset more than once. To elaborate:


require 'daru'

offset = Daru::DateOffset.new(months: 2, n: 4)
offset + DateTime.new(2011,5,2)
#=> #<DateTime: 2012-01-02T00:00:00+00:00 ((2455929j,0s,0n),+0s,2299161j)>

The specialized offset classes like MonthBegin, YearEnd, etc. all reside inside the Daru::Offsets namespace and can be used by simply calling .new on them. All accept an optional Integer argument that works like the :n option for Daru::DateOffset, i.e it applies the offset multiple times.

To elaborate, consider the YearEnd offset. This offsets the date to the nearest year end after itself:


require 'daru'

offset = Daru::Offsets::YearEnd.new
offset + DateTime.new(2012,5,1,5,2,1)
#=> #<DateTime: 2012-12-31T05:02:01+00:00 ((2456293j,18121s,0n),+0s,2299161j)>

# Passing an Integer into an Offsets object will apply the offset that many times:

offset = Daru::Offsets::MonthBegin.new(3)
offset + DateTime.new(2015,3,5)
#=> #<DateTime: 2015-06-01T00:00:00+00:00 ((2457175j,0s,0n),+0s,2299161j)>

Of special note is the Week offset. This offset can be ‘anchored’ to any week of the day that you specify. When this is done, the DateTime that is being offset will be offset to that day of the week.

For example, to anchor the Week offset to a Wednesday, pass ‘3’ as a value to the :weekday option:


require 'daru'

offset = Daru::Offsets::Week.new(weekday: 3)
date   = DateTime.new(2012,1,6)
date.wday #=> 5

o = offset + date
#=> #<DateTime: 2012-01-11T00:00:00+00:00 ((2455938j,0s,0n),+0s,2299161j)>
o.wday #=> 3

Likewise, the Week offset can be anchored on any day of the week, by simplying specifying the :weekday option. Indexing for days of the week starts from 0 for Sunday and goes on 6 for Saturday.

Offset string aliases

The most obvious use of date offsets is for creating DateTimeIndex objects with a fixed time interval between each date index. To make creation of indexes easy, each of the offset classes have been linked to certain string alaises, which can directly passed to the DateTimeIndex class.

For example, to create a DateTimeIndex of 100 periods with a frequency of 1 hour between each period:


require 'daru'

offset = Daru::DateTimeIndex.date_range(
  :start => '2015-4-4', :periods => 100, :freq => 'H')
#=> #<DateTimeIndex:86417320 offset=H periods=100 data=[2015-04-04T00:00:00+00:00...2015-04-08T03:00:00+00:00]>

Likewise all of the above listed offsets can be aliased using strings, which can be used for specifying the offset in a DateTimeIndex index. The string aliases of each offset class are as follows:

Alias String Offset Class / Description
‘S’ Second
‘M’ Minute
‘H’ Hour
‘D’ Days
‘W’ Default Week. Anchored on SUN.
‘W-SUN’ Week anchored on sunday
‘W-MON’ Week anchored on monday
‘W-TUE’ Week anchored on tuesday
‘W-WED’ Week anchored on wednesday
‘W-THU’ Week anchored on thursday
‘W-FRI’ Week anchored on friday
‘W-SAT’ Week anchored on saturday
‘MONTH’ Month
‘MB’ MonthBegin
‘ME’ MonthEnd
‘YEAR’ Year
‘YB’ YearBegin
‘YE’ YearEnd

See this notebook on daru’s time series functions in order to get a good overview of daru’s time series manipulation functionality.