diff --git a/assets/src/scripts/components/hydrograph/axes.js b/assets/src/scripts/components/hydrograph/axes.js
index c9133a4dcafc7056f7aaeb11eeb560d969d1bf90..3c9f97c75da3688f12f5b2b8155ead4cbc9dbb1d 100644
--- a/assets/src/scripts/components/hydrograph/axes.js
+++ b/assets/src/scripts/components/hydrograph/axes.js
@@ -1,249 +1,24 @@
-import { axisBottom, axisLeft, axisRight } from 'd3-axis';
+import {axisBottom, axisLeft, axisRight} from 'd3-axis';
 import memoize from 'fast-memoize';
-import { DateTime, Interval } from 'luxon';
-import { createSelector } from 'reselect';
+import {createSelector} from 'reselect';
 
-import config from '../../config';
-import { getCurrentDateRange, getCurrentParmCd } from '../../selectors/time-series-selector';
-import { convertCelsiusToFahrenheit, convertFahrenheitToCelsius, mediaQuery, deltaDays } from '../../utils';
+import {generateTimeTicks} from '../../d3-rendering/tick-marks';
+import {getCurrentDateRange, getCurrentParmCd} from '../../selectors/time-series-selector';
+import {convertCelsiusToFahrenheit, convertFahrenheitToCelsius} from '../../utils';
 
-import { getYTickDetails } from './domain';
+import {getYTickDetails} from './domain';
 import {getLayout} from './layout';
-import { getXScale, getBrushXScale, getYScale, getSecondaryYScale } from './scales';
-import { yLabelSelector, secondaryYLabelSelector, tsTimeZoneSelector, TEMPERATURE_PARAMETERS } from './time-series';
-
-
-const FORMAT = {
-    P7D: 'MMM dd',
-    P30D: 'MMM dd',
-    P1Y: 'MMM yyyy',
-    custom: null
-};
-
-/**
- * Generate the values for ticks to place on a hydrograph.
- *
- * @param startDate - start datetime in the form of milliseconds since 1970-01-01 UTC
- * @param endDate - end datetime in the form of milliseconds since 1970-01-01 UTC
- * @param ianaTimeZone - Internet Assigned Numbers Authority designation for a time zone
- * @returns {Object} with two properties, dates {Array of Number timestamp in milliseconds} and
- *      format {String} the format that should be used used to display the dates.
- */
-export const generateDateTicks = function(startDate, endDate, ianaTimeZone) {
-
-    const startDateTime = DateTime.fromMillis(startDate, {zone: ianaTimeZone});
-    const endDateTime = DateTime.fromMillis(endDate, {zone: ianaTimeZone});
-    const length = Interval.fromDateTimes(startDateTime, endDateTime);
-    const dayCount = length.count('days');
-    const weekCount = length.count('weeks');
-    const monthCount = length.count('months');
-    const yearCount = length.count('years');
-
-    const formatFnc = (format) => {
-        return function(dateTime)  {
-            return DateTime.fromMillis(dateTime, {zone: ianaTimeZone}).toFormat(format);
-        };
-    };
-
-    const getTicks = function(interval, startOffset ) {
-        let dateTime;
-        const startOffsetKind = Object.keys(startOffset)[0];
-        if (startOffsetKind === 'years') {
-            dateTime = startDateTime.startOf('year');
-        } else if (startOffsetKind === 'months') {
-            dateTime = startDateTime.startOf('month');
-        } else {
-            dateTime = startDateTime.startOf('day');
-        }
-        dateTime = dateTime.plus(startOffset);
-
-        let result = [];
-        while (dateTime < endDateTime) {
-            console.log(`${dateTime.toFormat('f')}`);
-            result.push(dateTime.toMillis());
-            dateTime = dateTime.plus(interval);
-        }
-        return result;
-    };
-
-    const getDefaultTicks = function (unit, tickCount) {
-        const tickInterval = (endDate - startDate) / (tickCount + 1);
-        let result = [];
-
-        let dateTime = DateTime.fromMillis(startDate + tickInterval, {zone: ianaTimeZone});
-        while (dateTime < endDateTime) {
-            let tickDateTime = dateTime.startOf(unit);
-            console.log(`Default ${tickDateTime.toFormat('f')}`);
-            result.push(tickDateTime.toMillis());
-            dateTime = dateTime.plus(tickInterval);
-        }
-
-        return result;
-    };
-
-    let result = {
-        dates: [],
-        format: null
-    };
-
-    if (dayCount <= 3) {
-        result = {
-            dates: getDefaultTicks('minute', 4),
-            format: formatFnc('MMM dd HH:mm')
-        };
-    } else if (dayCount > 3 && dayCount <= 8) {
-        // Tick marks are daily
-        result = {
-            dates: getTicks({days: 1}, {days: 1}),
-            format: formatFnc('MMM dd')
-        };
-
-    } else if (dayCount > 8 && dayCount <= 15) {
-        // Tick marks are ever other day
-        result = {
-            dates: getTicks({days: 2}, {days: 1}),
-            format: formatFnc('MMM dd')
-        };
-    } else if (dayCount > 15 && dayCount <= 29) {
-        //Tick marks every fourth day
-        result = {
-            dates: getTicks({days: 4}, {days: 1}),
-            format: formatFnc('MMM dd')
-        };
-    } else if (weekCount > 4 && weekCount <= 8) {
-        //Tick marks every week
-        result = {
-            dates: getTicks({weeks: 1}, {days: 3}),
-            format: formatFnc('MMM dd')
-        };
-    } else if (weekCount > 8 && weekCount <= 15) {
-        // Tick marks every other week
-        result = {
-            dates: getTicks({weeks: 2}, {days: 7}),
-            format: formatFnc('MMM dd')
-        };
-    } else if (weekCount > 15 && monthCount <= 8) {
-        //Tick marks every month
-        result = {
-            dates: getTicks({months: 1}, {months : 1}),
-            format: formatFnc('MMM yyyy')
-        };
-    } else if (monthCount > 8 && monthCount <= 15) {
-        //Tick marks every other month
-        result = {
-            dates: getTicks({months: 2}, {months: 1}),
-            format: formatFnc('MMM yyyy')
-        };
-    } else if (monthCount > 15 && monthCount <= 29){
-        // Tick marks every 4 months
-        result = {
-            dates: getTicks({months: 4}, {months: 2}),
-            format: formatFnc('MMM yyyy')
-        };
-    } else if (monthCount > 29 && monthCount <= 43) {
-        // Tick marks every 6 months
-        result = {
-            dates: getTicks({months: 6}, {months: 3}),
-            format: formatFnc('MMM yyyy')
-        };
-    } else if (monthCount > 43 && yearCount <= 8) {
-        // Tick marks every year
-        result = {
-            dates: getTicks({years: 1}, {years: 1}),
-            format: formatFnc('yyyy')
-        };
-    } else {
-        // Generate 8 tick marks and put them at the beginning of the year of that date.
-        result = {
-            dates: getDefaultTicks('year', 7),
-            format: formatFnc('yyyy')
-        };
-    }
-
-
-    return result;
-    /*
-    const tzStartDate = DateTime.fromMillis(startDate, {zone: ianaTimeZone});
-    let dates = [];
-    let date;
-    let timePeriod;
-    let interval;
-    let dateDiff;
-
-    const setP7D = () => {
-        date = tzStartDate.startOf('day');
-        timePeriod = 'days';
-        interval = 1;
-    };
-    const setP30D = () => {
-        date = tzStartDate.minus({days: tzStartDate.weekday}).startOf('day');
-        timePeriod = 'weeks';
-        interval = 1;
-    };
-    const setP1Y = () => {
-        date = tzStartDate.startOf('month');
-        timePeriod = 'months';
-        if (mediaQuery(config.USWDS_LARGE_SCREEN)) {
-            interval = 1;
-        } else {
-            interval = 2;
-        }
-    };
-    switch (period) {
-        case 'P7D':
-            setP7D();
-            break;
-        case 'P30D':
-            setP30D();
-            break;
-        case 'P1Y':
-            setP1Y();
-            break;
-        case 'custom':
-            dateDiff = deltaDays(new Date(startDate), new Date(endDate));
-            if (dateDiff <= 7) {
-                setP7D();
-                FORMAT.custom = 'MMM dd';
-            } else if (7 < dateDiff && dateDiff <= 30) {
-                setP30D();
-                FORMAT.custom = 'MMM dd';
-            } else if (30 < dateDiff && dateDiff <= 365) {
-                setP1Y();
-                FORMAT.custom = 'MMM yyyy';
-            } else {
-                date = tzStartDate.startOf('month');
-                timePeriod = 'months';
-                interval = Math.ceil(dateDiff/365.25);
-                FORMAT.custom = 'MMM yyyy';
-            }
-            break;
-        default:
-            date = tzStartDate.startOf('day');
-            timePeriod = 'days';
-            interval = 1;
-    }
-    while (date.valueOf() <= endDate) {
-        date = date.plus({[timePeriod]: interval});
-        if (startDate <= date.valueOf() && date.valueOf() <= endDate) {
-            dates.push(date.valueOf());
-        }
-    }
-    return dates;
-    */
-};
-
-
+import {getXScale, getBrushXScale, getYScale, getSecondaryYScale} from './scales';
+import {yLabelSelector, secondaryYLabelSelector, tsTimeZoneSelector, TEMPERATURE_PARAMETERS} from './time-series';
 
 const createXAxis = function(xScale,  period, ianaTimeZone) {
-    const [startDate, endDate] = xScale.domain();
-    const tickDates = generateDateTicks(startDate, endDate, period, ianaTimeZone);
+    const [startMillis, endMillis] = xScale.domain();
+    const ticks = generateTimeTicks(startMillis, endMillis, ianaTimeZone);
     return axisBottom()
         .scale(xScale)
-        .tickValues(tickDates)
+        .tickValues(ticks.dates)
         .tickSizeOuter(0)
-        .tickFormat(d => {
-            return DateTime.fromMillis(d, {zone: ianaTimeZone}).toFormat(FORMAT[period]);
-        });
+        .tickFormat(ticks.format);
 };
 
 /**
diff --git a/assets/src/scripts/components/hydrograph/axes.spec.js b/assets/src/scripts/components/hydrograph/axes.spec.js
deleted file mode 100644
index 13c82f30c514c92acf470242716cdf807268a020..0000000000000000000000000000000000000000
--- a/assets/src/scripts/components/hydrograph/axes.spec.js
+++ /dev/null
@@ -1,349 +0,0 @@
-import {DateTime} from 'luxon';
-
-import {generateDateTicks } from './axes';
-
-
-describe('Chart axes', () => {
-
-    const timeZone = 'America/Chicago';
-
-    fdescribe('generateDateTicks', () => {
-        const startTime = 1520538281000;
-
-        it('Generates 4 ticks with format MMM dd HH:mm when the day length is 2', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 2}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(4);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 08 23:20', 'Mar 09 08:56', 'Mar 09 18:32', 'Mar 10 04:08']
-            );
-        });
-
-        it('Generates day length tick marks with format MMM dd when length is 7 days', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 7}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 09', 'Mar 10', 'Mar 11', 'Mar 12', 'Mar 13', 'Mar 14', 'Mar 15']
-            );
-        });
-        it('Generates day length tick marks with format MMM dd when length is 4 days', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 3}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(3);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 09', 'Mar 10', 'Mar 11']
-            );
-        });
-
-        it('Generates every other day tick marks with format MMM dd when length is 8 days', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 8}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(4);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 09', 'Mar 11', 'Mar 13', 'Mar 15']
-            );
-        });
-
-        it('Generates every other day tick marks with format MM dd when length is 14', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 14}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 09', 'Mar 11', 'Mar 13', 'Mar 15', 'Mar 17', 'Mar 19', 'Mar 21']
-            );
-        });
-
-        it('Generates every fourth day tick marks with format MM dd when length is 15', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 15}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(4);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 09', 'Mar 13', 'Mar 17', 'Mar 21']
-            );
-        });
-
-        it('Generates every fourth day tick marks with format MM dd when length is 28', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 28}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 09', 'Mar 13', 'Mar 17', 'Mar 21', 'Mar 25', 'Mar 29', 'Apr 02']
-            );
-        });
-
-        it('Generates every week tick marks with format MM dd when day count is 29', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 29}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(4);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 11', 'Mar 18', 'Mar 25', 'Apr 01']
-            );
-        });
-
-        it('Generates every week tick marks with format MM dd when week count is 8', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 50}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 11', 'Mar 18', 'Mar 25', 'Apr 01', 'Apr 08', 'Apr 15', 'Apr 22']
-            );
-        });
-
-        it('Generates every two week tick marks with format MM dd when week count is 9', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 53}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(4);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 15', 'Mar 29', 'Apr 12', 'Apr 26']
-            );
-        });
-
-        it('Generates every two week tick marks with format MM dd when week count is 16', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 98}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Mar 15', 'Mar 29', 'Apr 12', 'Apr 26', 'May 10', 'May 24', 'Jun 07']
-            );
-        });
-
-        it('Generates every month tick marks with format MM YYYY when week count is 17', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({days: 126}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(4);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Apr 2018', 'May 2018', 'Jun 2018', 'Jul 2018']
-            );
-        });
-
-        it('Generates every month tick marks with format MM YYYY when month count is 7', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({month: 7, days: 1}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Apr 2018', 'May 2018', 'Jun 2018', 'Jul 2018', 'Aug 2018', 'Sep 2018', 'Oct 2018']
-            );
-        });
-
-        it('Generates every other month tick marks with format MM YYYY when month count is 8', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({month: 8, days: 18}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(4);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Apr 2018', 'Jun 2018', 'Aug 2018', 'Oct 2018']
-            );
-        });
-
-        it('Generates every other month tick marks with format MM YYYY when month count is 14', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({month: 14, days: 18}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Apr 2018', 'Jun 2018', 'Aug 2018', 'Oct 2018', 'Dec 2018', 'Feb 2019', 'Apr 2019']
-            );
-        });
-
-        it('Generates every four month tick marks with format MM YYYY when month count is 15', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({month: 15, days: 18}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(4);
-            expect(result.dates.map(result.format)).toEqual(
-                ['May 2018', 'Sep 2018', 'Jan 2019', 'May 2019']
-            );
-        });
-
-        it('Generates every four month tick marks with format MM YYYY when month count is 28', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({month: 28, days: 18}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['May 2018', 'Sep 2018', 'Jan 2019', 'May 2019', 'Sep 2019', 'Jan 2020', 'May 2020']
-            );
-        });
-
-        it('Generates every six month tick marks with format MM YYYY when month count is 29', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({month: 29, days: 18}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(5);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Jun 2018', 'Dec 2018', 'Jun 2019', 'Dec 2019', 'Jun 2020']
-            );
-        });
-
-        it('Generates every six month tick marks with format MM YYYY when month count is 43', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({month: 42, days: 18}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['Jun 2018', 'Dec 2018', 'Jun 2019', 'Dec 2019', 'Jun 2020', 'Dec 2020', 'Jun 2021']
-            );
-        });
-
-        it('Generates every year tick marks with format MM YYYY when month count is 44', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({month: 44, days: 18}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(3);
-            expect(result.dates.map(result.format)).toEqual(
-                ['2019', '2020', '2021']
-            );
-        });
-
-        it('Generates every year tick marks with format MM YYYY when year count is 8', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({year : 7}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['2019', '2020', '2021', '2022', '2023', '2024', '2025']
-            );
-        });
-
-        it('Generates 7 tick marks with format YYYY when year count is 9', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({year : 9}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['2019', '2020', '2021', '2022', '2023', '2024', '2026']
-            );
-        });
-
-        it('Generates 7 tick marks with format YYYY when year count is large', () => {
-            const endTime = DateTime.fromMillis(startTime).plus({year : 20}).toMillis();
-            const result = generateDateTicks(startTime, endTime, timeZone);
-
-            expect(result.dates.length).toBe(7);
-            expect(result.dates.map(result.format)).toEqual(
-                ['2020', '2023', '2025', '2028', '2030', '2033', '2035']
-            );
-        });
-
-
-/*
-        const endDate = 1504215240000;
-        const startP7D = 1503610440000;
-        const startP30D = 1501623240000;
-        const startP1Y = 1472679240000;
-        const startCustomUnderOneDecade = 1274590800000;
-        const startCustomOverTwoDecades = 651906000000;
-
-        it('creates tick marks for a 7 day period', () => {
-            const result = generateDateTicks(startP7D, endDate, 'P7D', timeZone);
-            expect(result).toEqual([
-                1503644400000,
-                1503730800000,
-                1503817200000,
-                1503903600000,
-                1503990000000,
-                1504076400000,
-                1504162800000
-            ]);
-        });
-
-        it('uses weekly ticks for 7 or fewer days for a custom date range', () => {
-            const result = generateDateTicks(startP7D, endDate, 'custom', timeZone);
-            expect(result).toEqual([
-                1503644400000,
-                1503730800000,
-                1503817200000,
-                1503903600000,
-                1503990000000,
-                1504076400000,
-                1504162800000
-            ]);
-        });
-
-        it('creates tick marks for a 30 day period', () => {
-            const result = generateDateTicks(startP30D, endDate, 'P30D', timeZone);
-            expect(result).toEqual([
-                1502002800000,
-                1502607600000,
-                1503212400000,
-                1503817200000
-            ]);
-        });
-
-        it('uses weekly ticks for a different of days 7 between 30 for a custom date range', () => {
-            const result = generateDateTicks(startP30D, endDate, 'custom', timeZone);
-            expect(result).toEqual([
-                1502002800000,
-                1502607600000,
-                1503212400000,
-                1503817200000
-            ]);
-        });
-
-        it('creates tick marks for a 1 year period', () => {
-            const result = generateDateTicks(startP1Y, endDate, 'P1Y', timeZone);
-            expect(result.length).toBeGreaterThanOrEqual(6);
-            expect(result.includes(1475305200000)).toBe(true);
-            expect(result.includes(1480579200000)).toBe(true);
-            expect(result.includes(1496300400000)).toBe(true);
-            expect(result.includes(1501570800000)).toBe(true);
-        });
-
-        it('custom uses monthly marks for 30 days through a year', () => {
-            const result = generateDateTicks(startP1Y, endDate, 'custom', timeZone);
-            expect(result.length).toBeGreaterThanOrEqual(6);
-            expect(result.includes(1475305200000)).toBe(true);
-            expect(result.includes(1480579200000)).toBe(true);
-            expect(result.includes(1496300400000)).toBe(true);
-            expect(result.includes(1501570800000)).toBe(true);
-        });
-
-        it('custom ticks are correctly generated for dates under one decade', () => {
-            const result = generateDateTicks(startCustomUnderOneDecade, endDate, 'custom', timeZone);
-            expect(result).toEqual([
-                1293868800000,
-                1314860400000,
-                1335855600000,
-                1357027200000,
-                1378018800000,
-                1398927600000,
-                1420099200000,
-                1441090800000,
-                1462086000000,
-                1483257600000
-            ]);
-        });
-
-        it('custom ticks use correctly for dates over two decades', () => {
-            const result = generateDateTicks(startCustomOverTwoDecades, endDate, 'custom', timeZone);
-            expect(result).toEqual([
-                723196800000,
-                796723200000,
-                870418800000,
-                944035200000,
-                1017648000000,
-                1091343600000,
-                1164960000000,
-                1238569200000,
-                1312182000000,
-                1385884800000,
-                1459494000000
-            ]);
-        });
-        */
-    });
-});
diff --git a/assets/src/scripts/d3-rendering/axes-spec.js b/assets/src/scripts/d3-rendering/axes-spec.js
deleted file mode 100644
index 7ff4d78434e796d72e785d42bb0a256bb517fbf9..0000000000000000000000000000000000000000
--- a/assets/src/scripts/d3-rendering/axes-spec.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import {select} from 'd3-selection';
-
-import {appendXAxis, appendYAxis, appendSecondaryYAxis, appendAxes} from './axes';
-
-describe('axes module', () => {
-    let svg, layout;
-
-    beforeEach(() => {
-        layout = {
-            width: 550,
-            height: 900,
-            margin: {
-                top: 10,
-                bottom: 10,
-                left: 25,
-                right: 25
-            }
-        };
-        svg = select('body').append('svg');
-    });
-
-    afterEach(() => {
-        svg.remove();
-    });
-
-    describe('appendXAxis', () => {
-        let xAxis;
-        beforeEach(() => {
-            xAxis = jasmine.createSpy('mockXAxis');
-
-        });
-        it('should render the xAxis', () =>  {
-            appendXAxis(svg, {xAxis, layout});
-
-            expect(svg.selectAll('.x-axis').size()).toBe(1);
-            expect(xAxis).toHaveBeenCalled();
-        });
-    });
-
-    describe('appendYAxis', () => {
-        let yAxis;
-        beforeEach(() => {
-            yAxis = jasmine.createSpy('mockYAxis');
-        });
-
-        it('should render the yAxis', () =>  {
-            appendYAxis(svg, {yAxis, layout, yTitle: 'The Y Axis Title'});
-
-            expect(svg.selectAll('.y-axis').size()).toBe(1);
-            expect(svg.selectAll('.y-axis-label').size()).toBe(1);
-            expect(svg.select('.y-axis-label').select('tspan').html()).toEqual('The Y Axis Title');
-            expect(yAxis).toHaveBeenCalled();
-        });
-    });
-
-    describe('appendSecondaryYAxis', () => {
-        let yAxis;
-        beforeEach(() => {
-            yAxis = jasmine.createSpy('mockYAxis');
-        });
-
-        it('should render the secondaryYAxis', () =>  {
-            appendSecondaryYAxis(svg, {yAxis, layout, yTitle: 'The Secondary Y Axis Title'});
-
-            expect(svg.selectAll('.secondary-y-axis').size()).toBe(1);
-            expect(svg.selectAll('.secondary-y-axis-label').size()).toBe(1);
-            expect(svg.select('.secondary-y-axis-label').select('tspan').html()).toEqual('The Secondary Y Axis Title');
-            expect(yAxis).toHaveBeenCalled();
-        });
-    });
-
-    describe('appendAxes', () => {
-        let xAxis, yAxis, secondaryYAxis;
-        beforeEach(() => {
-            xAxis = jasmine.createSpy('mockXAxis');
-            yAxis = jasmine.createSpy('mockYAxis');
-        });
-
-        it('should render all three axes if a secondaryYAxis is defined', () => {
-            secondaryYAxis = jasmine.createSpy('mockYAxis');
-            appendAxes(svg, {xAxis, yAxis, secondaryYAxis, layout, ytitle: 'One Title', secondaryYTitle: 'Two Title'});
-
-            expect(svg.selectAll('.x-axis').size()).toBe(1);
-            expect(svg.selectAll('.y-axis').size()).toBe(1);
-            expect(svg.selectAll('.y-axis-label').size()).toBe(1);
-            expect(svg.selectAll('.secondary-y-axis').size()).toBe(1);
-            expect(svg.selectAll('.secondary-y-axis-label').size()).toBe(1);
-        });
-
-        it('should render only one y axis if a secondaryYAxis is not defined', () => {
-            appendAxes(svg, {xAxis, yAxis, secondaryYAxis: null, layout, ytitle: 'One Title', secondaryYTitle: 'Two Title'});
-
-            expect(svg.selectAll('.x-axis').size()).toBe(1);
-            expect(svg.selectAll('.y-axis').size()).toBe(1);
-            expect(svg.selectAll('.y-axis-label').size()).toBe(1);
-            expect(svg.selectAll('.secondary-y-axis').size()).toBe(0);
-            expect(svg.selectAll('.secondary-y-axis-label').size()).toBe(0);
-        });
-    });
-});
\ No newline at end of file
diff --git a/assets/src/scripts/d3-rendering/tick-marks.js b/assets/src/scripts/d3-rendering/tick-marks.js
new file mode 100644
index 0000000000000000000000000000000000000000..e2d31191c2ed95b9f14cc6cf3e3b3f2174414685
--- /dev/null
+++ b/assets/src/scripts/d3-rendering/tick-marks.js
@@ -0,0 +1,171 @@
+import {DateTime, Interval} from 'luxon';
+
+/*
+ * Return ticks between startDateTime and endDateTime where the tick marks are interval apart and
+ * start at startOffset
+ * @param {DateTime} startDateTime
+ * @param {DateTime} endDateTime
+ * @param {Object} interval - a Luxon object that can be used in the .plus method
+ * @param {Object} startOffset - a Luxon object than can be used in the .plus method
+ * @return {Array of Number} - tick marks in milliseconds.
+ */
+const getTicks = function(startDateTime, endDateTime, interval, startOffset ) {
+    let dateTime;
+    const startOffsetKind = Object.keys(startOffset)[0];
+    if (startOffsetKind === 'years') {
+        dateTime = startDateTime.startOf('year');
+    } else if (startOffsetKind === 'months') {
+        dateTime = startDateTime.startOf('month');
+    } else {
+        dateTime = startDateTime.startOf('day');
+    }
+    dateTime = dateTime.plus(startOffset);
+
+    let result = [];
+    while (dateTime < endDateTime) {
+        console.log(`${dateTime.toFormat('f')}`);
+        result.push(dateTime.toMillis());
+        dateTime = dateTime.plus(interval);
+    }
+    return result;
+};
+
+/*
+ * Returns an array of tickCount tick marks between startDate and endDate. The tick marks will
+ * always start on unit where unit represents a string that can be used by the Luxon method .startOf.
+ * @param {Number} startMillis in milliseconds
+ * @param {Number} endMillis in milliseconds
+ * @param {String} unit - string that can be used with the luxon method .startOf
+ * @param {String} tickCount - the desired number of ticks
+ * @param {String} ianaTimeZone - used when converting time in milliseconds to DateTime.
+ * @return {Array of Number} - tick marks in milliseconds.
+ */
+const getDefaultTicks = function (startMillis, endMillis, unit, tickCount, ianaTimeZone) {
+        const tickInterval = (endMillis - startMillis) / (tickCount + 1);
+        const endDateTime = DateTime.fromMillis(endMillis, {zone: ianaTimeZone});
+        let result = [];
+
+        let dateTime = DateTime.fromMillis(startMillis + tickInterval, {zone: ianaTimeZone});
+        while (dateTime < endDateTime) {
+            let tickDateTime = dateTime.startOf(unit);
+            console.log(`Default ${tickDateTime.toFormat('f')}`);
+            result.push(tickDateTime.toMillis());
+            dateTime = dateTime.plus(tickInterval);
+        }
+
+        return result;
+    };
+
+/**
+ * Generate the values for ticks to place on a time series graph along with an appropriate format function
+ * that can be used to produce a string representing the tick value. This should be used for time series that have
+ * minute accuracy.
+ *
+ * @param startMillis - start datetime in the form of milliseconds since 1970-01-01 UTC
+ * @param endMillis - end datetime in the form of milliseconds since 1970-01-01 UTC
+ * @param ianaTimeZone - Internet Assigned Numbers Authority designation for a time zone
+ * @returns {Object} with two properties, dates {Array of Number timestamp in milliseconds} and
+ *      format {String} the format that should be used used to display the dates.
+ */
+export const generateTimeTicks = function(startMillis, endMillis, ianaTimeZone) {
+    const startDateTime = DateTime.fromMillis(startMillis, {zone: ianaTimeZone});
+    const endDateTime = DateTime.fromMillis(endMillis, {zone: ianaTimeZone});
+    const length = Interval.fromDateTimes(startDateTime, endDateTime);
+    const dayCount = length.count('days');
+    const weekCount = length.count('weeks');
+    const monthCount = length.count('months');
+    const yearCount = length.count('years');
+
+    const formatFnc = (format) => {
+        return function(timeInMillis)  {
+            return DateTime.fromMillis(timeInMillis, {zone: ianaTimeZone}).toFormat(format);
+        };
+    };
+
+    let result = {
+        dates: [],
+        format: null
+    };
+
+    if (length.count('hours') <= 4) {
+        result = {
+            dates: getDefaultTicks(startMillis, endMillis, 'minute', 4, ianaTimeZone),
+            format: formatFnc('MMM dd HH:mm')
+        };
+    } else if (dayCount <= 3) {
+        // Generates 4 tick marks that are on the start of a minute
+        result = {
+            dates: getDefaultTicks(startMillis, endMillis,'hour', 4, ianaTimeZone),
+            format: formatFnc('MMM dd HH:mm')
+        };
+    } else if (dayCount > 3 && dayCount <= 8) {
+        // Tick marks are daily
+        result = {
+            dates: getTicks(startDateTime, endDateTime,{days: 1}, {days: 1}),
+            format: formatFnc('MMM dd')
+        };
+
+    } else if (dayCount > 8 && dayCount <= 15) {
+        // Tick marks are ever other day
+        result = {
+            dates: getTicks(startDateTime, endDateTime,{days: 2}, {days: 1}),
+            format: formatFnc('MMM dd')
+        };
+    } else if (dayCount > 15 && dayCount <= 29) {
+        //Tick marks every fourth day
+        result = {
+            dates: getTicks(startDateTime, endDateTime,{days: 4}, {days: 1}),
+            format: formatFnc('MMM dd')
+        };
+    } else if (weekCount > 4 && weekCount <= 8) {
+        //Tick marks every week
+        result = {
+            dates: getTicks(startDateTime, endDateTime,{weeks: 1}, {days: 3}),
+            format: formatFnc('MMM dd')
+        };
+    } else if (weekCount > 8 && weekCount <= 15) {
+        // Tick marks every other week
+        result = {
+            dates: getTicks(startDateTime, endDateTime,{weeks: 2}, {days: 7}),
+            format: formatFnc('MMM dd')
+        };
+    } else if (weekCount > 15 && monthCount <= 8) {
+        //Tick marks every month
+        result = {
+            dates: getTicks(startDateTime, endDateTime,{months: 1}, {months : 1}),
+            format: formatFnc('MMM yyyy')
+        };
+    } else if (monthCount > 8 && monthCount <= 15) {
+        //Tick marks every other month
+        result = {
+            dates: getTicks(startDateTime, endDateTime,{months: 2}, {months: 1}),
+            format: formatFnc('MMM yyyy')
+        };
+    } else if (monthCount > 15 && monthCount <= 29){
+        // Tick marks every 4 months
+        result = {
+            dates: getTicks(startDateTime, endDateTime,{months: 4}, {months: 2}),
+            format: formatFnc('MMM yyyy')
+        };
+    } else if (monthCount > 29 && monthCount <= 43) {
+        // Tick marks every 6 months
+        result = {
+            dates: getTicks(startDateTime, endDateTime,{months: 6}, {months: 3}),
+            format: formatFnc('MMM yyyy')
+        };
+    } else if (monthCount > 43 && yearCount <= 8) {
+        // Tick marks every year
+        result = {
+            dates: getTicks(startDateTime, endDateTime,{years: 1}, {years: 1}),
+            format: formatFnc('yyyy')
+        };
+    } else {
+        // Generate 7 tick marks and put them at the beginning of the year of that date.
+        result = {
+            dates: getDefaultTicks(startMillis, endMillis, 'year', 7, ianaTimeZone),
+            format: formatFnc('yyyy')
+        };
+    }
+
+    return result;
+};
\ No newline at end of file
diff --git a/assets/src/scripts/d3-rendering/tick-marks.spec.js b/assets/src/scripts/d3-rendering/tick-marks.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..96926de3ccfe32bb54ba21f000059aec78fa75c8
--- /dev/null
+++ b/assets/src/scripts/d3-rendering/tick-marks.spec.js
@@ -0,0 +1,288 @@
+import {DateTime} from 'luxon';
+
+import {generateTimeTicks} from './tick-marks';
+
+describe('generateTimeTicks', () => {
+    const startTime = 1520538281000;
+    const timeZone = 'America/Chicago';
+
+    it('Generates 4 ticks when the hours length is less than 4', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({hours: 3}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(4);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 08 14:20', 'Mar 08 14:56', 'Mar 08 15:32', 'Mar 08 16:08']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).second).toBe(0);
+    });
+
+    it('Generates 4 ticks when the hours length is greater than 4', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({hours: 5}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(4);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 08 14:00', 'Mar 08 15:00', 'Mar 08 16:00', 'Mar 08 17:00']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).minute).toBe(0);
+    });
+
+    it('Generates 4 ticks with format MMM dd HH:mm when the day length is 2', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 2}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(4);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 08 23:00', 'Mar 09 08:00', 'Mar 09 18:00', 'Mar 10 04:00']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).second).toBe(0);
+    });
+
+    it('Generates day length tick marks with format MMM dd when length is 7 days', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 7}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 09', 'Mar 10', 'Mar 11', 'Mar 12', 'Mar 13', 'Mar 14', 'Mar 15']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).hour).toBe(0);
+    });
+
+    it('Generates day length tick marks with format MMM dd when length is 4 days', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 3}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(3);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 09', 'Mar 10', 'Mar 11']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).hour).toBe(0);
+    });
+
+    it('Generates every other day tick marks with format MMM dd when length is 8 days', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 8}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(4);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 09', 'Mar 11', 'Mar 13', 'Mar 15']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).hour).toBe(0);
+    });
+
+    it('Generates every other day tick marks with format MMM dd when length is 14', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 14}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 09', 'Mar 11', 'Mar 13', 'Mar 15', 'Mar 17', 'Mar 19', 'Mar 21']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).hour).toBe(0);
+    });
+
+    it('Generates every fourth day tick marks with format MMM dd when length is 15', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 15}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(4);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 09', 'Mar 13', 'Mar 17', 'Mar 21']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).hour).toBe(0);
+    });
+
+    it('Generates every fourth day tick marks with format MMM dd when length is 28', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 28}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 09', 'Mar 13', 'Mar 17', 'Mar 21', 'Mar 25', 'Mar 29', 'Apr 02']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).hour).toBe(0);
+    });
+
+    it('Generates every week tick marks with format MM dd when day count is 29', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 29}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(4);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 11', 'Mar 18', 'Mar 25', 'Apr 01']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).hour).toBe(0);
+    });
+
+    it('Generates every week tick marks with format MM dd when week count is 8', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 50}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 11', 'Mar 18', 'Mar 25', 'Apr 01', 'Apr 08', 'Apr 15', 'Apr 22']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).hour).toBe(0);
+    });
+
+    it('Generates every two week tick marks with format MM dd when week count is 9', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 53}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(4);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 15', 'Mar 29', 'Apr 12', 'Apr 26']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).hour).toBe(0);
+    });
+
+    it('Generates every two week tick marks with format MM dd when week count is 16', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 98}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Mar 15', 'Mar 29', 'Apr 12', 'Apr 26', 'May 10', 'May 24', 'Jun 07']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).hour).toBe(0);
+    });
+
+    it('Generates every month tick marks with format MM YYYY when week count is 17', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({days: 126}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(4);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Apr 2018', 'May 2018', 'Jun 2018', 'Jul 2018']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+
+    it('Generates every month tick marks with format MM YYYY when month count is 7', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({month: 7, days: 1}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Apr 2018', 'May 2018', 'Jun 2018', 'Jul 2018', 'Aug 2018', 'Sep 2018', 'Oct 2018']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+
+    it('Generates every other month tick marks with format MM YYYY when month count is 8', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({month: 8, days: 18}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(4);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Apr 2018', 'Jun 2018', 'Aug 2018', 'Oct 2018']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+
+    it('Generates every other month tick marks with format MM YYYY when month count is 14', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({month: 14, days: 18}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Apr 2018', 'Jun 2018', 'Aug 2018', 'Oct 2018', 'Dec 2018', 'Feb 2019', 'Apr 2019']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+
+    it('Generates every four month tick marks with format MM YYYY when month count is 15', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({month: 15, days: 18}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(4);
+        expect(result.dates.map(result.format)).toEqual(
+            ['May 2018', 'Sep 2018', 'Jan 2019', 'May 2019']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+
+    it('Generates every four month tick marks with format MM YYYY when month count is 28', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({month: 28, days: 18}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['May 2018', 'Sep 2018', 'Jan 2019', 'May 2019', 'Sep 2019', 'Jan 2020', 'May 2020']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+
+    it('Generates every six month tick marks with format MM YYYY when month count is 29', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({month: 29, days: 18}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(5);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Jun 2018', 'Dec 2018', 'Jun 2019', 'Dec 2019', 'Jun 2020']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+
+    it('Generates every six month tick marks with format MM YYYY when month count is 43', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({month: 42, days: 18}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['Jun 2018', 'Dec 2018', 'Jun 2019', 'Dec 2019', 'Jun 2020', 'Dec 2020', 'Jun 2021']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+
+    it('Generates every year tick marks with format YYYY when month count is 44', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({month: 44, days: 18}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(3);
+        expect(result.dates.map(result.format)).toEqual(
+            ['2019', '2020', '2021']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).month).toBe(1);
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+
+    });
+
+    it('Generates every year tick marks with format MM YYYY when year count is 8', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({year: 7}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['2019', '2020', '2021', '2022', '2023', '2024', '2025']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).month).toBe(1);
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+
+    it('Generates 7 tick marks with format YYYY when year count is 9', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({year: 9}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['2019', '2020', '2021', '2022', '2023', '2024', '2026']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).month).toBe(1);
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+
+    it('Generates 7 tick marks with format YYYY when year count is large', () => {
+        const endTime = DateTime.fromMillis(startTime).plus({year: 20}).toMillis();
+        const result = generateTimeTicks(startTime, endTime, timeZone);
+
+        expect(result.dates.length).toBe(7);
+        expect(result.dates.map(result.format)).toEqual(
+            ['2020', '2023', '2025', '2028', '2030', '2033', '2035']
+        );
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).month).toBe(1);
+        expect(DateTime.fromMillis(result.dates[0], {zone: timeZone}).day).toBe(1);
+    });
+});
\ No newline at end of file
diff --git a/assets/src/scripts/index.spec.js b/assets/src/scripts/index.spec.js
index d76d52388f7970f3c6810c864b8cbd97cc523819..b37f248ced2fbd81126b13c743ed9ea902e75ec7 100644
--- a/assets/src/scripts/index.spec.js
+++ b/assets/src/scripts/index.spec.js
@@ -8,17 +8,19 @@
  */
 
 import './polyfills';
-/*
+
 import './ajax.spec';
 
 import './d3-rendering/accessibility.spec';
 import './d3-rendering/alerts.spec';
 import './d3-rendering/axes.spec';
 import './d3-rendering/cursor-slider.spec';
-import './d3-rendering/loading-indicator.spec';
 import './d3-rendering/graph-tooltip.spec';
-import './d3-rendering/markers.spec';
 import './d3-rendering/legend.spec';
+import './d3-rendering/loading-indicator.spec';
+import './d3-rendering/markers.spec';
+import './d3-rendering/tick-marks.spec';
+
 
 import './components/dailyValueHydrograph/selectors/labels.spec';
 import './components/dailyValueHydrograph/selectors/scales.spec';
@@ -32,9 +34,6 @@ import './components/dailyValueHydrograph/tooltip.spec';
 import './components/embed.spec';
 
 import './components/hydrograph/audible.spec';
- */
-import './components/hydrograph/axes.spec';
-/*
 import './components/hydrograph/cursor.spec';
 import './components/hydrograph/date-controls.spec';
 import './components/hydrograph/domain.spec';
@@ -86,4 +85,3 @@ import './web-services/models.spec';
 import './web-services/nldi-data.spec';
 import './web-services/observations-spec';
 import './web-services/statistics-data.spec';
-*/
\ No newline at end of file
diff --git a/assets/src/scripts/utils.js b/assets/src/scripts/utils.js
index 200c309c9dc397b7b4eeec2c409cc1a7bad000b9..0d5d3520ee03c6ec54655b0624af7e2a93d250d8 100644
--- a/assets/src/scripts/utils.js
+++ b/assets/src/scripts/utils.js
@@ -45,23 +45,6 @@ export const replaceHtmlEntities = function (someString) {
     return someString;
 };
 
-/**
- * Calculate the difference in days between two Date objects
- *
- * @param date1
- * @param date2
- * @returns {number}
- */
-export const deltaDays = function (date1, date2) {
-    let one_day_ms = 24*60*60*1000;
-    let date1_ms = date1.getTime();
-    let date2_ms = date2.getTime();
-
-    let delta_ms = date2_ms - date1_ms;
-
-    return Math.round(delta_ms/one_day_ms);
-};
-
 /**
  * Determine if two sets are equal
  *
diff --git a/assets/src/scripts/utils.spec.js b/assets/src/scripts/utils.spec.js
index 3bd77fd821791a81648f8bd16adbff3300f83117..1556f1937bd7d186b3d1bdda375595f8b501dc5f 100644
--- a/assets/src/scripts/utils.spec.js
+++ b/assets/src/scripts/utils.spec.js
@@ -1,6 +1,6 @@
 import {select} from 'd3-selection';
 import {
-    unicodeHtmlEntity, getHtmlFromString, deltaDays, replaceHtmlEntities, setEquality,
+    unicodeHtmlEntity, getHtmlFromString, replaceHtmlEntities, setEquality,
     wrap, mediaQuery, calcStartTime, callIf, parseRDB, convertFahrenheitToCelsius,
     convertCelsiusToFahrenheit, sortedParameters, getNearestTime} from './utils';
 
@@ -32,29 +32,6 @@ describe('Utils module', () => {
         });
     });
 
-    describe('deltaDays', () => {
-
-        const date1 = new Date(2017, 2, 26, 16, 15, 0);
-        const date2 = new Date(2017, 3, 2, 4, 30, 0);
-        const date3 = new Date(2017, 3, 2, 21, 15, 0);
-        const date4 = new Date(2017, 2, 30, 16, 15, 0);
-
-        it('Returns the correct number of days when it is a bit less than an integer number of days', () => {
-           let result = deltaDays(date1, date2);
-           expect(result).toBe(7);
-        });
-
-        it('Returns the correct number of days when it is a bit more than an integer number of days', () => {
-           let result = deltaDays(date1, date3);
-           expect(result).toBe(7);
-        });
-
-        it('Returns the correct number of days when it is an exact integer number days', () => {
-           let result = deltaDays(date1, date4);
-           expect(result).toBe(4);
-        });
-    });
-
     describe('replaceHtmlEntities', () => {
 
         it('replaces html entities with unicode', () => {