Skip to content

Commit

Permalink
Merge pull request #1 from calogica/add/date-dimension
Browse files Browse the repository at this point in the history
Adds date dimension and date-helper functions
  • Loading branch information
clausherther authored Oct 6, 2019
2 parents 437524a + 367eb70 commit b8ed174
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 8 deletions.
65 changes: 60 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ For example, use `America/New_York` for East Coast Time.

## Macros

### Date Dimension

#### get_date_dimension ([source](macros/get_date_dimension.sql))
Returns query to build date dimension from/to specified dates, including a number of useful columns based on each date.
See the [example model](models/examples/dim_date.sql) for details.

Usage:

```python
{{ dbt_date.get_date_dimension('2015-01-01', '2022-12-31') }}
```

### Date

#### convert_timezone ([source](macros/date/convert_timezone.sql))
Expand Down Expand Up @@ -50,19 +62,47 @@ Using named parameters, we can also specify the source only and rely on the conf
{{ dbt_date.convert_timezone('my_column', source_tz='UTC') }}
```

#### now ([source](macros/date/now.sql))
Gets time based on local timezone (specified). Default is "America/Los_Angeles".
#### date_part ([source](macros/date/date_part.sql))
Extracts date parts from date.

Usage:

```python
{{ dbt_date.now() }}
{{ dbt_date.date_part('dayofweek', 'date_day') }} as day_of_week
```

or, specify a timezone:
#### day_name ([source](macros/date/day_name.sql))
Extracts name of weekday from date.

Usage:

```python
{{ dbt_date.now('America/New_York') }}
{{ dbt_date.day_name('date_day', short=true) }} as day_of_week_short_name,
{{ dbt_date.day_name('date_day', short=false) }} as day_of_week_long_name
```

#### last_week ([source](macros/date/last_week.sql))
Convenience function to get the start date of last week

Wraps:
```python
{{ dbt_date.n_weeks_ago(1, tz) }}
```

Usage:
```python
{{ dbt_date.last_week()) }}
```
```python
{{ dbt_date.last_week(tz='America/New_York)) }}
```

#### month_name ([source](macros/date/month_name.sql))
Extracts name of month from date.

```python
{{ dbt_date.month_name('date_day', short=true) }} as month_short_name,
{{ dbt_date.month_name('date_day', short=false) }} as month_long_name
```

#### n_days_ago ([source](macros/date/n_days_ago.sql))
Expand Down Expand Up @@ -119,6 +159,21 @@ Usage:
{{ dbt_date.n_weeks_away(4) }}
```

#### now ([source](macros/date/now.sql))
Gets time based on local timezone (specified). Default is "America/Los_Angeles".

Usage:

```python
{{ dbt_date.now() }}
```

or, specify a timezone:

```python
{{ dbt_date.now('America/New_York') }}
```

#### periods_since ([source](macros/date/periods_since.sql))
Returns the number of periods since a specified date.

Expand Down
2 changes: 1 addition & 1 deletion dbt_project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ macro-paths: ["macros"]
log-path: "logs"

require-dbt-version: ">=0.14.0"

profile: dev
quoting:
identifier: false
schema: false
Expand Down
4 changes: 2 additions & 2 deletions macros/date/convert_timezone.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
{{ adapter_macro('dbt_date.convert_timezone', column, target_tz, source_tz) }}
{% endmacro %}

{% macro default__convert_timezone(column, target_tz=None, source_tz=None) %}
{% macro default__convert_timezone(column, target_tz, source_tz) %}
{%- if not source_tz -%}
cast(convert_timezone('{{ target_tz }}', {{ column }}) as {{ dbt_utils.type_timestamp() }})
{%- else -%}
cast(convert_timezone('{{ source_tz }}', '{{ target_tz }}', {{ column }}) as {{ dbt_utils.type_timestamp() }})
{%- endif -%}
{% endmacro %}

{% macro bigquery__convert_timezone(column, target_tz=None, source_tz=None) %}
{% macro bigquery__convert_timezone(column, target_tz, source_tz=None) %}
datetime({{ column }}, '{{ target_tz}}')
{% endmacro %}
11 changes: 11 additions & 0 deletions macros/date/date_part.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% macro date_part(datepart, date) -%}
{{ adapter_macro('dbt_date.date_part', datepart, date) }}
{%- endmacro %}

{% macro default__date_part(datepart, date) -%}
date_part('{{ datepart }}', {{ date }})
{%- endmacro %}

{% macro bigquery__date_part(datepart, date) -%}
extract({{ datepart }} from {{ date }})
{%- endmacro %}
13 changes: 13 additions & 0 deletions macros/date/day_name.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% macro day_name(date, short=True) -%}
{{ adapter_macro('dbt_date.day_name', date, short) }}
{%- endmacro %}

{% macro default__day_name(date, short) -%}
{% set f = 'Dy' if short else 'Day' %}
to_char({{ date }}, '{{ f }}')
{%- endmacro %}

{% macro bigquery__day_name(date, short) -%}
{% set f = '%a' if short else '%A' %}
format_date('{{ f }}', cast({{ date }} as date))
{%- endmacro %}
13 changes: 13 additions & 0 deletions macros/date/month_name.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% macro month_name(date, short=True) -%}
{{ adapter_macro('dbt_date.month_name', date, short) }}
{%- endmacro %}

{% macro default__month_name(date, short) -%}
{% set f = 'MON' if short else 'MONTH' %}
to_char({{ date }}, '{{ f }}')
{%- endmacro %}

{% macro bigquery__month_name(date, short) -%}
{% set f = '%b' if short else '%B' %}
format_date('{{ f }}', cast({{ date }} as date))
{%- endmacro %}
15 changes: 15 additions & 0 deletions macros/get_base_dates.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{% macro get_base_dates(start_date, end_date) %}
with dates as
(
{{ dbt_utils.date_spine(
datepart="day",
start_date="cast('" ~ start_date ~ "' as datetime)",
end_date="cast('" ~ end_date ~ "' as datetime)",
)
}}
)
select
d.date_day
from
dates d
{% endmacro %}
63 changes: 63 additions & 0 deletions macros/get_date_dimension.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{% macro get_date_dimension(start_date, end_date) %}
{{ adapter_macro('dbt_date.get_date_dimension', start_date, end_date) }}
{% endmacro %}

{% macro default__get_date_dimension(start_date, end_date) %}
with base_dates as (
{{ dbt_date.get_base_dates(start_date, end_date) }}
),
dates_with_prior_year_dates as (
select
cast(d.date_day as date) as date_day,
cast({{ dbt_utils.dateadd('year', -1 , 'd.date_day') }} as date) as prior_year_date_day,
cast({{ dbt_utils.dateadd('day', -364 , 'd.date_day') }} as date) as prior_year_over_year_date_day
from
base_dates d
)
select
d.date_day,
cast({{ dbt_utils.dateadd('day', -1 , 'd.date_day') }} as date) as prior_date_day,
cast({{ dbt_utils.dateadd('day', 1 , 'd.date_day') }} as date) as next_date_day,
d.prior_year_date_day as prior_year_date_day,
d.prior_year_over_year_date_day,
cast(
case
when {{ dbt_date.date_part('dayofweek', 'd.date_day') }} = 0 then 7
else {{ dbt_date.date_part('dayofweek', 'd.date_day') }}
end
as {{ dbt_utils.type_int() }}
) as day_of_week,

{{ dbt_date.day_name('d.date_day', short=false) }} as day_of_week_name,
{{ dbt_date.day_name('d.date_day', short=true) }} as day_of_week_name_short,
cast({{ dbt_date.date_part('day', 'd.date_day') }} as {{ dbt_utils.type_int() }}) as day_of_month,
cast({{ dbt_date.date_part('dayofyear', 'd.date_day') }} as {{ dbt_utils.type_int() }}) as day_of_year,

cast({{ dbt_utils.date_trunc('week', 'd.date_day') }} as date) as week_start_date,
cast({{ dbt_utils.last_day('d.date_day', 'week') }} as date) as week_end_date,
cast({{ dbt_date.date_part('week', 'd.date_day') }} as {{ dbt_utils.type_int() }}) as week_of_year,
cast({{ dbt_utils.date_trunc('week', 'd.prior_year_over_year_date_day') }} as date) as prior_year_week_start_date,
cast({{ dbt_utils.last_day('d.prior_year_over_year_date_day', 'week') }} as date) as prior_year_week_end_date,
cast({{ dbt_date.date_part('week', 'd.prior_year_over_year_date_day') }} as {{ dbt_utils.type_int() }}) as prior_year_week_of_year,

cast({{ dbt_date.date_part('month', 'd.date_day') }} as {{ dbt_utils.type_int() }}) as month_of_year,
{{ dbt_date.month_name('d.date_day', short=false) }} as month_name,
{{ dbt_date.month_name('d.date_day', short=true) }} as month_name_short,

cast({{ dbt_utils.date_trunc('month', 'd.date_day') }} as date) as month_start_date,
cast({{ dbt_utils.last_day('d.date_day', 'month') }} as date) as month_end_date,

cast({{ dbt_utils.date_trunc('month', 'd.prior_year_date_day') }} as date) as prior_year_month_start_date,
cast({{ dbt_utils.last_day('d.prior_year_date_day', 'month') }} as date) as prior_year_month_end_date,

cast({{ dbt_date.date_part('quarter', 'd.date_day') }} as {{ dbt_utils.type_int() }}) as quarter_of_year,
cast({{ dbt_utils.date_trunc('quarter', 'd.date_day') }} as date) as quarter_start_date,
cast({{ dbt_utils.last_day('d.date_day', 'quarter') }} as date) as quarter_end_date,

cast({{ dbt_date.date_part('year', 'd.date_day') }} as {{ dbt_utils.type_int() }}) as year_number,
cast({{ dbt_utils.date_trunc('year', 'd.date_day') }} as date) as year_start_date,
cast({{ dbt_utils.last_day('d.date_day', 'year') }} as date) as year_end_date
from
dates_with_prior_year_dates d
order by 1
{% endmacro %}
6 changes: 6 additions & 0 deletions models/examples/dim_date.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{{
config(
materialized = 'ephemeral'
)
}}
{{ dbt_date.get_date_dimension('2015-01-01', '2022-12-31') }}

0 comments on commit b8ed174

Please sign in to comment.