
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

<html>
    <head>
        <meta charset="utf-8">
        <script src="lib/esl.js"></script>
        <script src="lib/config.js"></script>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="stylesheet" href="lib/reset.css" />
    </head>
    <body>
        <style>
            h1 {
                background: #ddd;
                text-align: center;
                font-weight: bold;
                font-size: 14px;
                padding: 20px 0;
            }
            .chart {
                height: 350px;
            }
        </style>


        <h1>time scale label should in local time when timestamp (in UTC) input, tick should align with day.</h1>
        <div class="chart" id="chart0"></div>

        <h1>
            time scale label should in UTC time when option.useUTC is `true`, tick should not align with day.<br>
            tooltip (default) should be OK.
        </h1>
        <div class="chart" id="chart1"></div>

        <h1>
            time scale label should in UTC time when option.useUTC is `true`, tick should not align with day.<br>
            tooltip (formatter: series0 2017-02-09 16:00) should be OK.
        </h1>
        <div class="chart" id="chart1-1"></div>

        <h1>useUTC: null, should display '00:00 01-03' in tooltip on the 1st point</h1>
        <div class="chart" id="chart2"></div>

        <h1>useUTC: true, should display '16:00 01-02' in tooltip on the 1st point</h1>
        <div class="chart" id="chart3"></div>














        <script>
            var dataTimestamp = [
                [1486656000000, 20000],
                [1486742400000, 30000],
                [1486828800000, 10000],
                [1486915200000, 290000],
                [1487001600000, 123355],
                [1487088000000, 198128],
                [1487174400000, 123124]
            ];

            var dataTimeString = [
                ['2012-01-03', 20000],
                ['2012-01-04', 30000],
                ['2012-01-05', 10000],
                ['2012-01-06', 290000]
            ];

            // opt: {useUTC, tooltipFormatter}
            function makeTimeScaleOption(data, opt) {
                opt = opt || {};
                var useUTC = opt.useUTC;
                var tooltipFormatter = opt.tooltipFormatter;
                return {
                    useUTC: useUTC,
                    tooltip: {
                        trigger: 'axis',
                        // test in Safari (NaN-NaN-NaN NaN:NaN:NaN)
                        formatter: tooltipFormatter
                    },
                    xAxis: [{
                        type: 'time',
                        splitNumber: 7,
                        axisLabel: {
                            formatter: function (tick) {
                                return echarts.time.format(
                                    tick,
                                    '{yyyy}-{MM}-{dd} {HH}:{mm}:{ss}',
                                    useUTC
                                );
                            },
                            rotate: 10
                        },
                        splitLine: {
                            show: false
                        }
                    }],
                    yAxis: [{
                        type: 'value',
                        splitLine: {
                            show: false
                        }
                    }],
                    series: [{
                        type: 'line',
                        smooth: true,
                        data: data,
                        label: {
                            show: true,
                            formatter: function (params) {
                                return echarts.time.format(
                                    params.value[0],
                                    '{yyyy}-{MM}-{dd} {HH}:{mm}:{ss}',
                                    useUTC
                                );
                            }
                        }
                    }]
                };
            }


        </script>





        <script>

            var echarts;
            var colorTool;
            var chart;
            var myChart;
            var groupCategories = [];
            var groupColors = [];

            require([
                'echarts'
            ], function (ec) {
                echarts = ec;
                colorTool = echarts.color;
                var dom = document.getElementById('chart0');
                if (!dom) {
                    return;
                }
                chart = myChart = echarts.init(dom);

                var option = makeTimeScaleOption(dataTimestamp);

                chart.setOption(option);
            });

        </script>








        <script>

            var echarts;
            var colorTool;
            var chart;
            var myChart;
            var groupCategories = [];
            var groupColors = [];

            require([
                'echarts'
            ], function (ec) {
                echarts = ec;
                colorTool = echarts.color;
                var dom = document.getElementById('chart1');
                if (!dom) {
                    return;
                }
                chart = myChart = echarts.init(dom);

                var option = makeTimeScaleOption(dataTimestamp, {useUTC: true});

                chart.setOption(option);
            });

        </script>









        <script>

            var echarts;
            var colorTool;
            var chart;
            var myChart;
            var groupCategories = [];
            var groupColors = [];

            require([
                'echarts'
            ], function (ec) {
                echarts = ec;
                colorTool = echarts.color;
                var dom = document.getElementById('chart1-1');
                if (!dom) {
                    return;
                }
                chart = myChart = echarts.init(dom);

                var option = makeTimeScaleOption(
                    dataTimestamp,
                    {useUTC: true, tooltipFormatter: '{a0} {yyyy}-{MM}-{dd} {HH}:{mm}:{ss}'}
                );

                chart.setOption(option);
            });

        </script>











        <script>

            var echarts;
            var colorTool;
            var chart;
            var myChart;
            var groupCategories = [];
            var groupColors = [];

            require([
                'echarts'
            ], function (ec) {
                echarts = ec;
                colorTool = echarts.color;
                var dom = document.getElementById('chart2');
                if (!dom) {
                    return;
                }
                chart = myChart = echarts.init(dom);

                var option = makeTimeScaleOption(dataTimeString);

                chart.setOption(option);
            });

        </script>











        <script>

            var echarts;
            var colorTool;
            var chart;
            var myChart;
            var groupCategories = [];
            var groupColors = [];

            require([
                'echarts'
            ], function (ec) {
                echarts = ec;
                colorTool = echarts.color;
                var dom = document.getElementById('chart3');
                if (!dom) {
                    return;
                }
                chart = myChart = echarts.init(dom);

                var option = makeTimeScaleOption(dataTimeString, {useUTC: true});

                chart.setOption(option);
            });

        </script>




    </body>
</html>
