
<!--
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/simpleRequire.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>
