Dates, Times and Timezones

The ChartIQ library displays "time series" charts. Time series charts display dates on the x-axis. To understand the x-axis, it is critical to understand how the library works with dates.

Developers feed an array of data points into a chart (Data Loading Tutorials). Each data point requires a value (Close) and a date (DT or Date). The array of these data points is plotted to create a chart.

Often, the server is in a different timezone than the user. We call the server's timezone the "dataZone" and the user's timezone the "displayZone". By default, the displayZone is set to the timezone of the user's browser and operating system. This means that data sent by the server is converted to the browser's timezone before being displayed on the x-axis. This is very helpful to the user!

Dates and Times

Why are there two possible fields to represent a date?

DT

Use DT when you have a JavaScript Date() object or a value that can be coerced into a Date() object. For instance, DT can take an epoch (number of milliseconds since 1970 GMT) or a ISO 8601 standard string. JavaScript dates are timezone independent. This is because they are implicitly based on UTC (universal time). Each of the coercable formats (epoch, ISO 8601) contain a timezone offset that allows the browser to convert to local time.

Example, data being sent to the library with an epoch :

dataObj={
    DT: new Date(134534934343),
    Close: 100.12
}

Example, data being sent to the library in ISO 8601 format :

dataObj={
    DT: new Date("1997-07-16T19:20:30+01:00"),
    Close: 100.12
}

Date

Use Date when your dates are in string format. A wide variety of string formats are accepted. String dates generally do not contain timezone information, so when using string form dates you must explicitly tell the chart which timezone the data is from (usually the server or exchange's time zone). The chart will convert the dates based on the timezone provided. (See Timezones below).

Example, data being sent to the library in string format :

dataObj={
    Date: "1997/07/16 19:20:30",
    Close: 100.12
}

The library supports many string formats:

  • MM/DD/YYYY
  • YYYY-MM-DD
  • YYYYMMDDhhmm
  • YYYYMMDDhhmmssmmm
  • YYYY/MM/DD hh:mm
  • MM-DD hh:mm

Regardless of whether you provide DT or Date, the chart will convert and add the other. So if you provide DT, the chart will calculate the Date. If you provide the Date, then the chart will calculate the DT. If you examine the chart's masterData, dataSet or dataSegment you will see both dates.

Timezones

Note: Timezones only affect intraday charts.

Everybody in the world lives in a timezone that is determined from an offset of Greenwich Mean Time (GMT). GMT is sometimes called "Universal Time" or "UTC". Your timezone is based on an offset from UTC. For many timezones, the offset will change throughout the year depending on whether daylight savings time (DST) is in effect.

The time displayed on your computer is determined by the timezone you've selected in your operating system. Your browser's clock is based on this time, and so the charting library is also based on this time. The default behavior of the charting library is to convert data from its source timezone to a timezone of the user's local computer. There are two timezone variables that affect this behavior:

  • dataZone The timezone for the data from your server (the "from" timezone).
  • displayZone The timezone to display on the x-axis. (the "to" timezone). If this is not set (default) then the chart assumes conversions will be to the browser's local timezone.
Timezone Conversion

When you provide a chart with data, the first thing it needs to do is calculate the difference in time zones from your server data (dataZone) and the browser itself. There are four possibilities:

1) If you pass a DT (UTC format) then the chart automatically knows the time zone of your market data. The chart will automatically print x-axis times in the browser's local timezone.

2) If you pass a Date (string format), you must explicitly set the time zone by calling setTimeZone(dataZone) where the dataZone is the known time zone of your server (e.g. America/New_York).

Example, data comes from Hong Kong but display in user's local time:

stxx.setTimeZone("Asia/Hong_Kong");
// load data

3) If you want the chart to always display in the server's timezone (no conversion) then do not set either dataZone or displayZone.

4) If you provide data in UTC format, but wish to display in the exchange's timezone then you will need to set the displayZone programatically

Example, force data to display in Hong Kong time even if data is provided as UTC:

stxx.setTimeZone(null, "Asia/Hong_Kong");
// load UTC data
Timezone Menu For Users

The default template, template-advanced.html, includes a TimeZone web component that allows users to select their time zone (to override the browser's default). The component simply calls CIQ.ChartEngine#setTimeZone with the timezone selected by the user.

Example, user selected timezone :

var userSelected="America/New_York"; // for instance, from a menu
stxx.setTimeZone(null, userSelected); // passing null as the first parameter won't affect a previously set dataZone

The list of all accepted timezones is contained in CIQ.timeZoneMap.

Market Hours

The x-axis of a stock chart does not generally follow calendar time because few securities trade 24 hours per day, and almost no securities trade 7 days per week. For a stock chart to properly display portions of the x-axis, it must be aware of the hours that a security trades. It must know the exchange or market hours. Accurately iterating through "market hours" is important for such tasks as plotting out the future x-axis, accurately maintaining drawings across periodicities or detecting data gaps.

It is also important to note that only data within the defined market hours will be displayed on the chart even if more data is loaded.

Knowing the market hours for NYSE, the chart can accurately project the x-axis into the future. Note how the x-axis starts a new market day at 16:00 : X-Axis Projected Into The Future

The days, hours and holiday schedule for a market can be defined with a "Market Definition" object. Here is an example of a market definition object:


    var myMarket = {
        name: "My Market",
        market_tz: "America/Chicago", // Note you must specify the time zone for the market!
        rules: [
                {"dayofweek": 0, "open": "15:00", "close": "24:00"}, // Sunday
                {"dayofweek": 1, "open": "00:00", "close": "24:00"},
                {"dayofweek": 2, "open": "00:00", "close": "24:00"},
                {"dayofweek": 3, "open": "00:00", "close": "24:00"},
                {"dayofweek": 4, "open": "00:00", "close": "24:00"},
                {"dayofweek": 5, "open": "00:00", "close": "18:00"},
                {"date": "*-12-25", "open": "00:00", "close": "00:00"} // closed on Christmas
        ]
    };

ChartIQ maintains market definitions for major world markets. These can be found in the exchangeHours.js file (NYSE, GLOBEX and METALS are defined in the core library).

If you are dealing with a single exchange, then simply provide the market definition to your chart:

stxx.setMarket(CIQ.Market.NYSE);

See CIQ.ChartEngine#setMarket for details.

Market Factories

Supporting multiple exchanges with different markets requires implementing a "Market Factory". A Market Factory is simply a callback function that takes a stock symbol and returns a market definition. This concept is referred to as "symbology". One firm may use the symbol "IBM.NY" to represent IBM on the New York Stock Exchange. Another firm may use "IBM NYSE" or even just "IBM". A Market Factory must be written to parse your symbology, determine the market, and return the appropriate market definition class.

Here is an example market factory:

// Market Class Example 1
var NYSE = {
    "name": "NYSE",
    "market_tz": "America/New_York",
    "rules": []     // define all necessary rules
};

// Market Class Example 2
var XLON = {
    "name": "XLON",
    "market_tz": "Europe/London",
    "rules": []     // define all necessary rules
};

// symbolObject contains all info needed about a financial instrument (symbol)
var myFactory = function(symbolObject){
    var symbol = symbolObject.symbol;

    if(symbol.indexOf(".NY")!=-1) return NYSE;
    if(symbol.indexOf(".LS")!=-1) return XLON;
    return NYSE; // default if no match
};

stxx.setMarketFactory(myFactory);
stxx.newChart('IBM'); // library will call myFactory and assign a market to the chart

Whenever the user changes the symbol, the chart will make a call to the market factory and load the returned market definition file. It will do this before displaying the chart, so that the x-axis always accurately reflects the trading hours for the security.

The ChartIQ library contains a pre-defined factory, CIQ.Market.Symbology.factory that supports a common symbology used by Xignite and Yahoo Finance.

Notes

timezone.js contains a modified version of the third party library timezone-js. All of the ChartIQ library functions that deal with time zones use timezoneJS.Date for date conversions.

A comprehensive list of available time zones are available in CIQ.timeZoneMap.

Actual time zones have changed over the years. Historical charts created by ChartIQ are accurate thanks to the historical information compiled by the Internet Assigned Numbers Authority (IANA). ChartIQ periodically updates the timezone database that is bundled into the library.

CIQ date formatting functions


    // built-in library functions for date formatting
    stxx.strToDateTime('01/01/17 12:00:00'); // convert to Javascript date/time
    stxx.strToDate(datetimeString); // convert to Javascript date (no time)
    stxx.mmddyyyy(date) // convert date to MM/DD/YYYY format
    stxx.mmddhhmm(date) // convert date to MM-DD hh:mm
    stxx.yyyymmdd(date) // convert date to YYYY-MM-DD format
    stxx.yyyymmddhhmm(date) // convert date to YYYYMMDDhhmm format
    stxx.yyyymmddhhmmssmmm(date) // convert date to YYYYMMDDhhmmssmmm format
    stxx.friendlyDate(date) // convert date to YYYY/MM/DD hh:mm format
    stxx.standardUTCDate(date) // convert date to YYYY-MM-DDThh:mm:ssZ format

Next Steps: