<div class="theme-toggle">
  <input type="checkbox" id="theme-switch">
  <label for="theme-switch">
    <div class="toggle"></div>
    <div class="names">
      <p class="light">Light</p>
      <p class="dark">Dark</p>
    </div>
  </label>
</div>

<script>
  (function() {
    var sw = document.getElementById('theme-switch');
    var html = document.getElementsByTagName('html')[0];
    var themeData = loadThemeData();

    function saveThemeData(data) {
      localStorage.setItem('theme', JSON.stringify(data));
    }

    function loadThemeData() {
      var data = localStorage.getItem('theme');
      try {
        data = JSON.parse(data ? data : '');
      } catch(e) {
        data = { nightShift: null, autoToggleAt: 0 };
        saveThemeData(data);
      }
      return data;
    }

    function handleThemeToggle(nightShift) {
      themeData.nightShift = nightShift;
      saveThemeData(themeData);
      html.dataset.theme = nightShift ? 'dark' : 'light';
      setTimeout(function() {
        sw.checked = nightShift ? true : false;
      }, 50);
    }

    function autoThemeToggle() {
      // Next time point of theme toggle
      var now = new Date();
      var toggleAt = new Date();
      var hours = now.getHours();
      var nightShift = hours >= 19 || hours <=7;

      if (nightShift) {
        if (hours > 7) {
          toggleAt.setDate(toggleAt.getDate() + 1);
        }
        toggleAt.setHours(7);
      } else {
        toggleAt.setHours(19);
      }

      toggleAt.setMinutes(0);
      toggleAt.setSeconds(0);
      toggleAt.setMilliseconds(0)

      var delay = toggleAt.getTime() - now.getTime();

      // auto toggle theme mode
      setTimeout(function() {
        handleThemeToggle(!nightShift);
      }, delay);

      return {
        nightShift: nightShift,
        toggleAt: toggleAt.getTime()
      };
    }

    var data = autoThemeToggle();

    // Listen the theme toggle event
    sw.addEventListener('change', function(event) {
      handleThemeToggle(event.target.checked);
    });

    // Toggle theme by local setting
    if (data.toggleAt > themeData.autoToggleAt) {
      themeData.autoToggleAt = data.toggleAt;
      handleThemeToggle(data.nightShift);
    } else {
      handleThemeToggle(themeData.nightShift);
    }
  })();
</script>