Dates in Tableau. This post will be useful for those who... | by Amanda Monzon | Towards Data Science

This post will be useful for those who are working with financial data or anyone who is tracking how the business is doing compared to last years numbers.
User wants to track how sales are doing to the previous year on a macro and micro level (YTD, Day YOY).
Switch between date fields — when working with financial data users want to see how sales are doing as orders come in but also want to track when they are booked in an accounting system. Building in the ability for the user to easily switch between these two date fields while only keeping one set of reports and charts.Drill up and down — when using date fields to build a time series chart, Tableau includes the ability to drill date parts up and down. But not all users know to hover over the date axis to view the -/+ or you want to limit the users ability too drill to far up or down.Date Compare — the Relative Date Range filter can be used to select YTD, MTD, and Today but does not allow Year over Year (YOY) or Rolling date range comparison. Build in the most common date range comparison to allow for YOY and Rolling period. Additionally, capability to change the end date to track how far away from previous years sales.
Switch between date fields — when working with financial data users want to see how sales are doing as orders come in but also want to track when they are booked in an accounting system. Building in the ability for the user to easily switch between these two date fields while only keeping one set of reports and charts.
Drill up and down — when using date fields to build a time series chart, Tableau includes the ability to drill date parts up and down. But not all users know to hover over the date axis to view the -/+ or you want to limit the users ability too drill to far up or down.
Date Compare — the Relative Date Range filter can be used to select YTD, MTD, and Today but does not allow Year over Year (YOY) or Rolling date range comparison. Build in the most common date range comparison to allow for YOY and Rolling period. Additionally, capability to change the end date to track how far away from previous years sales.
The workbook below displays the end result of each step with the final tab “Time Series” bringing everything together. I decided to show how to build each component using continuous and discrete because there are use cases for both depending on requirements.
public.tableau.com
WARNING row-level calculations involving parameters such as the ones in this workbook will increase load time. Check out this Interworks post.
Built upon Carl Slifer’s Interworks post on date comparison made easy.
Using parameters can easily change between two or more date fields.
Step 1. Create a parameter field, [Select Date field]. Setting the data type to integer will help performance since integer and boolean data types run faster than date and string data types. Each value can be given a name that is easily recognized.
Step 2. Create the calculation [Select Date field]
CASE [Parameters].[Select Date field]WHEN 1 THEN [Order Date]WHEN 2 THEN [Ship Date]END
Step 3. Place the calculation in a view and show the parameter.
Below I built two charts using the [Select Date field] calculation. Notice the continuous chart has no breaks in the lines and each Month/Year is not labeled while the discrete chart has breaks in the line and each year, quarter and month is labeled.
Build a parameter to switch to different date levels.
Step 1. Create [Date View] parameter
Step 2. Create Date View calculation. Notice that I will be using the [Select Date field] created in the previous step. If you do not need to switch between dates then the desired date field can be used.
Date View_Continuous
CASE [Parameters].[Date View]WHEN 5 THEN DATE(DATETRUNC('year', [Select Date field]))WHEN 1 THEN DATE(DATETRUNC('quarter', [Select Date field]))WHEN 2 THEN DATE(DATETRUNC('month', [Select Date field]))WHEN 3 THEN DATE(DATETRUNC('week', [Select Date field]))WHEN 4 THEN DATE(DATETRUNC('day', [Select Date field]))END
Date View_Discrete
CASE [Parameters].[Date View]WHEN 5 THEN DATENAME('year',[Select Date field])WHEN 1 THEN DATENAME('year',[Select Date field]) + ' Q' + DATENAME('quarter',[Select Date field])WHEN 2 THEN DATENAME('year',[Select Date field]) + '-' + STR(DATEPART('month',[Select Date field]))WHEN 3 THEN DATENAME('year',[Select Date field]) + ' W' + STR(DATEPART('week',[Select Date field]))WHEN 4 THEN DATENAME('year',[Select Date field]) + '-' + STR(DATEPART('month',[Select Date field])) + '-' + STR(DATEPART('day',[Select Date field]))END
Step 3. Place on view
Continuous
On a Mac, hold down “option” key, select [Date View_Continuous] and place on columns. A new Drop Field window will pop up, select the first option “Date View_Continuous (Continuous)” which will not assign a static date part and allow the parameter to work properly.
Discrete
Move the [Date View_Discrete] to columns, by default date parts will not be applied.
Lets compare the two time series. Now we see the discrete time series does not contain breaks. I also prefer the discrete labels since it labels the date based on the date view selected. Where the continuous time series will adjust based on the date view selected, for months it displays the day which can be misleading to users.
Relative dates allow users to select YTD, MTD, and Day but does not allow Year over Year or Rolling period comparison.
For easy Year over Year and Rolling period comparison we will create 2 parameters; the first [End Date Chooser] will determine when the end date will be, the second [Date Compare to] will tell what type of date range to look at. Below are the 7 date comparisons that I typically heard users request. These comparisons can be grouped into three buckets; Year to Date, Rolling period, Year over Year. Each of the end dates will be determined based on the [End Date Chooser]. On the Date Compare dashboard, play with the selections to see how the date ranges change.
Year to Date: begins the first day of the calendar year
1. Year to Date (e.g., 9/15/2018)
2. Year to Day of Week (e.g., Monday, Tuesday)
Rolling period: consecutive days
3. Rolling Year to Date
Year over Year: current results for the same time period in the previous year
4. Quarter to Date
5. Month to Date
6. Date (e.g., 9/15/2018)
7. Day of Week (e.g., Monday, Tuesday)
Building the [End Date Chooser] first create the parameter
Then build the [End Date Chooser] calculation. This can be adjusted depending on how often the data is updated. Most of the time default to Yesterday since in many cases extracts are refreshed once per day. The Month End selections (e.g., Current, Previous, -2 Months, Current Year End) come in handy when users need to track what is happening YTD and MTD.
DATE(Case [Parameters].[End Date Chooser]WHEN 1 THEN TODAY()WHEN 2 THEN DATEADD('day', -1, TODAY())WHEN 3 THEN { MAX([Select Date field]) }WHEN 4 THEN [Custom End Date]WHEN 5 THEN DATEADD('day',-1,DATEADD('month',1,DATETRUNC('month',TODAY())))WHEN 6 THEN DATEADD('day',-1,DATETRUNC('month',TODAY()))WHEN 7 THEN DATEADD('day',-1,DATEADD('month', -1, DATETRUNC('month',TODAY())))WHEN 8 THEN DATEADD('day',-1,DATEADD('month', -2, DATETRUNC('month',TODAY())))WHEN 9 THEN DATEADD('day',-1,DATEADD('month', -3, DATETRUNC('month',TODAY())))WHEN 10 THEN DATEADD('day',-1,DATEADD('month', -4, DATETRUNC('month',TODAY())))WHEN 11 THEN DATEADD('day',-1,DATEADD('month', -5, DATETRUNC('month',TODAY())))WHEN 12 THEN DATEADD('day',-1,DATEADD('month', -6, DATETRUNC('month',TODAY())))WHEN 13 THEN DATEADD('day',-1,DATEADD('month', -7, DATETRUNC('month',TODAY())))WHEN 14 THEN DATEADD('day',-1,DATEADD('month', -8, DATETRUNC('month',TODAY())))WHEN 15 THEN DATEADD('day',-1,DATEADD('month', -9, DATETRUNC('month',TODAY())))WHEN 16 THEN DATEADD('day',-1,DATEADD('month', -10, DATETRUNC('month',TODAY())))WHEN 17 THEN DATEADD('day',-1,DATEADD('year', 1, DATETRUNC('year',TODAY())))END)
Next create the [Date Compare to] parameter.
Create [Date Compare to] calculation
CASE [Parameters].[Date Compare to]//Year To DateWHEN 1 THEN//CurrentIIF( DATEPART('dayofyear',[Select Date field]) <= DATEPART('dayofyear',[End Date Chooser])AND YEAR([Select Date field]) - YEAR([End Date Chooser]) = 0, 0//Previous, IIF( [Select Date field] <=DATEPARSE('MM-dd-yyyy',(STR(MONTH([End Date Chooser]))+'-'+STR(DAY([End Date Chooser]))+'-'+STR(YEAR(DATEADD('year',-1, [End Date Chooser])))))AND YEAR([Select Date field]) - YEAR([End Date Chooser]) = -1, -1, NULL))//Year to WeekdayWHEN 2 THEN//CurrentIIF( DATEPART('dayofyear',[Select Date field]) <= DATEPART('dayofyear',[End Date Chooser])AND YEAR([Select Date field]) - YEAR([End Date Chooser]) = 0, 0//Previous, IIF(  YEAR([Select Date field]) - YEAR([End Date Chooser]) = -1AND DATEPART('week', [Select Date field])*10 + DATEPART('weekday', [Select Date field])<= DATEPART('week', [End Date Chooser])*10 + DATEPART('weekday', [End Date Chooser]), -1, NULL))//Rolling  Year to DateWHEN 3 THEN//The first statement sets the conditions for a date to be considered the “current period.”//It will check every date to the date we've chosen as our starting point.//It must be based on whatever date we’ve chosen and go back a user chosen number of months, weeks, days, etc.//If the difference between these dates is >=0 and < our Period Length, we consider it to be the “current period.”IIF( DATEDIFF('day',[Select Date field],[End Date Chooser]) >=0AND DATEDIFF('day',[Select Date field],[End Date Chooser])< 365, 0//The second statement sets the conditions for a date to be considered the “previous period.”//It will compare every date to the date we've chosen as our starting point.//It will be based on whatever date we've chosen and it will immediately precede the “current period” and be the same length.//If the difference between the dates is > the Period Length but also < two times the length, it will be the “previous period.”, IIF( DATEDIFF('day',[Select Date field],[End Date Chooser]) >= 365AND DATEDIFF('day',[Select Date field],[End Date Chooser]) < 2*365, -1, NULL))//Quarter to DateWHEN 4 THEN//CurrentIIF( [Select Date field] <= [End Date Chooser]AND DATEDIFF('quarter',[Select Date field],[End Date Chooser])= 0, 0//Previous, IIF(  [Select Date field] <=DATEPARSE('MM-dd-yyyy',(STR(MONTH([End Date Chooser]))+'-'+STR(DAY([End Date Chooser]))+'-'+STR(YEAR(DATEADD('year',-1, [End Date Chooser])))))AND DATEDIFF('quarter',[Select Date field],[End Date Chooser]) = 4, -1, NULL))//Month to DateWHEN 5 THEN//CurrentIIF( [Select Date field] <= [End Date Chooser]AND DATEDIFF('month',[Select Date field],[End Date Chooser])= 0, 0//Previous, IIF( DAY([Select Date field]) <= DAY([End Date Chooser])AND DATEDIFF('month',[Select Date field],[End Date Chooser])= 12, -1, NULL))//DateWHEN 6 THEN//CurrentIIF( DATEDIFF('day',[Select Date field],[End Date Chooser])= 0, 0//Previous, IIF( [Select Date field] =DATEPARSE('MM-dd-yyyy',(STR(MONTH([End Date Chooser]))+'-'+STR(DAY([End Date Chooser]))+'-'+STR(YEAR(DATEADD('year',-1, [End Date Chooser]))))), -1, NULL))//WeekdayWHEN 7 THEN//CurrentIIF( DATEDIFF('day',[Select Date field],[End Date Chooser])= 0, 0//Previous, IIF(  YEAR([Select Date field]) - YEAR([End Date Chooser]) = -1AND DATEPART('week', [Select Date field])*10 + DATEPART('weekday', [Select Date field])= DATEPART('week', [End Date Chooser])*10 + DATEPART('weekday', [End Date Chooser]), -1, NULL))END
This last step we will create a date field that only uses the current year so we can have the previous and current period displayed on a time series with the month/day matching.
Create a calculation [Date Mth/Day/CY]. This will create a new date field that matches the month and day and uses the [End Date Chooser’] to grab the current period year. Additional logic is added to account for leap years where there is an extra day in February. If this is not added then Feb-29 will end up in March.
DATE(STR(MONTH([Select Date field]))+"/"+IIF(DATEPART('day',[Select Date field]) = 29 AND DATEPART('month',[Select Date field]) = 2,STR(DAY(DATEADD('day', -1, [Select Date field]))),STR(DAY([Select Date field])))+"/"+STR(YEAR([End Date Chooser])))
Then create the [Date View_Continuous] and [Date View_Discrete] based on the logic in the previous section switching the date to [Date Mth/Day/CY].
Now we have the final view that meets the original use case described at the beginning of this post. The final workbook can be viewed here.