[网站模板]日期时间选择器插件 - 开发者工具,响应式,支持暗黑模式,html纯静态源码

日期时间选择器插件:提供日期选择和时间选择功能

双标签切换:支持日期选择和时间选择两个独立面板

交互式日历:可切换月份,点击选择日期,显示今日标记

时间调节控件:通过上下按钮或直接输入调整小时和分钟

暗黑/亮色模式:右上角一键切换,保存用户偏好到 Cookie

响应式设计:适配手机和桌面设备

核心功能:日期选择(日历面板),时间选择(小时/分钟调节),确认选择(弹窗显示结果),重置(恢复当前时间)

适用场景:开发者工具、表单组件、后台管理系统

html Copier le code
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>日期时间选择器插件 - 开发者工具</title>
    <meta name="keywords" content="日期时间选择器插件|开发者工具" />
    <meta name="description" content="日期时间选择器插件工具网站" />
    <style>
      :root {
        --bg-primary: #f8f9fa;
        --bg-secondary: #ffffff;
        --text-primary: #212529;
        --text-secondary: #6c757d;
        --border-color: #dee2e6;
        --accent-color: #4361ee;
        --hover-color: #e9ecef;
        --shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      }

      .dark-mode {
        --bg-primary: #121212;
        --bg-secondary: #1e1e1e;
        --text-primary: #f8f9fa;
        --text-secondary: #adb5bd;
        --border-color: #343a40;
        --accent-color: #4cc9f0;
        --hover-color: #2d2d2d;
        --shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
      }

      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        transition:
          background-color 0.3s,
          color 0.3s,
          border-color 0.3s;
      }

      body {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        background-color: var(--bg-primary);
        color: var(--text-primary);
        display: flex;
        justify-content: center;
        /*align-items: center;*/
        min-height: 100vh;
        padding: 20px;
      }

      .container {
        width: 100%;
        max-width: 900px;
        text-align: center;
      }

      .header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 30px;
      }

      h2 {
        font-weight: 600;
        color: var(--text-primary);
      }

      .logo {
        color: #00b4ff;
        font-family: 华文楷体, serif;
        text-decoration: none;
        font-size: 28px;
      }

      .theme-switch {
        position: relative;
        display: inline-block;
        width: 60px;
        height: 30px;
      }

      .theme-switch input {
        opacity: 0;
        width: 0;
        height: 0;
      }

      .slider {
        position: absolute;
        cursor: pointer;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: #ccc;
        transition: 0.4s;
        border-radius: 34px;
      }

      .slider:before {
        position: absolute;
        content: '';
        height: 22px;
        width: 22px;
        left: 4px;
        bottom: 4px;
        background-color: white;
        transition: 0.4s;
        border-radius: 50%;
      }

      input:checked + .slider {
        background-color: var(--accent-color);
      }

      input:checked + .slider:before {
        transform: translateX(30px);
      }

      .datetime-container {
        background: var(--bg-secondary);
        border-radius: 12px;
        box-shadow: var(--shadow);
        overflow: hidden;
        margin-bottom: 20px;
        border: 1px solid var(--border-color);
      }

      .tabs {
        display: flex;
        background: var(--bg-primary);
        border-bottom: 1px solid var(--border-color);
      }

      .tab {
        padding: 15px 20px;
        flex: 1;
        cursor: pointer;
        font-weight: 500;
        color: var(--text-secondary);
      }

      .tab.active {
        color: var(--accent-color);
        border-bottom: 3px solid var(--accent-color);
        background: var(--bg-secondary);
      }

      .tab-content {
        display: none;
        padding: 25px;
      }

      .tab-content.active {
        display: block;
        animation: fadeIn 0.5s ease;
      }

      @keyframes fadeIn {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }

      .calendar {
        margin-bottom: 20px;
      }

      .calendar-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 15px;
      }

      .calendar-header button {
        background: none;
        border: none;
        font-size: 18px;
        cursor: pointer;
        color: var(--text-secondary);
        padding: 5px 10px;
        border-radius: 5px;
        transition: background 0.3s;
      }

      .calendar-header button:hover {
        background: var(--hover-color);
      }

      .calendar-header h2 {
        color: var(--text-primary);
        font-size: 18px;
        font-weight: 500;
      }

      .weekdays {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        font-weight: 500;
        color: var(--text-secondary);
        margin-bottom: 10px;
      }

      .weekdays div {
        padding: 10px 0;
        text-align: center;
      }

      .days {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        gap: 5px;
      }

      .days div {
        padding: 12px 0;
        text-align: center;
        cursor: pointer;
        border-radius: 50%;
        transition: all 0.3s;
        color: var(--text-primary);
      }

      .days div:hover {
        background: var(--hover-color);
      }

      .days div.selected {
        background: var(--accent-color);
        color: white;
      }

      .days div.other-month {
        color: var(--text-secondary);
      }

      .days div.today {
        border: 1px solid var(--accent-color);
      }

      .time-selector {
        display: flex;
        justify-content: center;
        gap: 15px;
        margin-bottom: 20px;
      }

      .time-section {
        text-align: center;
      }

      .time-section label {
        display: block;
        margin-bottom: 8px;
        color: var(--text-secondary);
        font-weight: 500;
      }

      .time-input {
        display: flex;
        flex-direction: column;
        align-items: center;
      }

      .time-input button {
        background: none;
        border: none;
        font-size: 16px;
        cursor: pointer;
        color: var(--text-secondary);
        padding: 5px;
        border-radius: 5px;
        transition: background 0.3s;
      }

      .time-input button:hover {
        background: var(--hover-color);
      }

      .time-input input {
        width: 60px;
        text-align: center;
        padding: 10px;
        border: 1px solid var(--border-color);
        border-radius: 8px;
        font-size: 18px;
        margin: 5px 0;
        background: var(--bg-primary);
        color: var(--text-primary);
      }

      .actions {
        display: flex;
        justify-content: center;
        gap: 15px;
        margin-top: 20px;
      }

      .btn {
        padding: 12px 25px;
        border: none;
        border-radius: 8px;
        cursor: pointer;
        font-weight: 500;
        transition: all 0.3s;
      }

      .btn-primary {
        background: var(--accent-color);
        color: white;
      }

      .btn-primary:hover {
        opacity: 0.9;
        transform: translateY(-2px);
      }

      .btn-secondary {
        background: var(--bg-primary);
        color: var(--text-secondary);
        border: 1px solid var(--border-color);
      }

      .btn-secondary:hover {
        background: var(--hover-color);
      }

      .selected-date {
        margin-top: 20px;
        font-size: 18px;
        color: var(--text-primary);
        padding: 15px;
        background: var(--bg-secondary);
        border-radius: 8px;
        display: inline-block;
        border: 1px solid var(--border-color);
      }

      @media (max-width: 600px) {
        .datetime-container {
          border-radius: 8px;
        }

        .tab-content {
          padding: 15px;
        }

        .time-selector {
          flex-direction: column;
          align-items: center;
          gap: 10px;
        }

        .actions {
          flex-direction: column;
        }

        .btn {
          width: 100%;
        }

        .header {
          flex-direction: column;
          gap: 15px;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="header">
        <h1>日期时间选择器</h1>
        <div class="theme-toggle">
          <label class="theme-switch">
            <input type="checkbox" id="theme-toggle" />
            <span class="slider"></span>
          </label>
          <div style="margin-top: 8px; font-size: 14px; color: var(--text-secondary)">
            <span id="theme-label">暗黑模式</span>
          </div>
        </div>
      </div>

      <div class="datetime-container">
        <div class="tabs">
          <div class="tab active" data-tab="date">日期选择</div>
          <div class="tab" data-tab="time">时间选择</div>
        </div>

        <div class="tab-content active" id="date-tab">
          <div class="calendar">
            <div class="calendar-header">
              <button id="prev-month">&lt;</button>
              <h2 id="current-month"></h2>
              <button id="next-month">&gt;</button>
            </div>

            <div class="weekdays">
              <div>日</div>
              <div>一</div>
              <div>二</div>
              <div>三</div>
              <div>四</div>
              <div>五</div>
              <div>六</div>
            </div>

            <div class="days" id="calendar-days">
              <!-- Days will be populated by JavaScript -->
            </div>
          </div>
        </div>

        <div class="tab-content" id="time-tab">
          <div class="time-selector">
            <div class="time-section">
              <label>小时</label>
              <div class="time-input">
                <button id="hour-up">↑</button>
                <input type="text" id="hour" value="" maxlength="2" />
                <button id="hour-down">↓</button>
              </div>
            </div>

            <div class="time-section">
              <label>分钟</label>
              <div class="time-input">
                <button id="minute-up">↑</button>
                <input type="text" id="minute" value="" maxlength="2" />
                <button id="minute-down">↓</button>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="actions">
        <button class="btn btn-secondary" id="btn-cancel">重置</button>
        <button class="btn btn-primary" id="btn-confirm">确认选择</button>
      </div>

      <div class="selected-date" id="selected-date"></div>
    </div>

    <script>
      document.addEventListener('DOMContentLoaded', function () {
        // 当前选择的日期和时间
        let selectedDate = new Date()
        let selectedHour = 12
        let selectedMinute = 0

        // 初始化主题
        function initTheme() {
          const theme = getCookie('theme_datetime')
          const themeToggle = document.getElementById('theme-toggle')
          const themeLabel = document.getElementById('theme-label')

          if (theme === 'dark') {
            document.body.classList.add('dark-mode')
            themeToggle.checked = true
            themeLabel.textContent = '暗黑模式'
          } else {
            document.body.classList.remove('dark-mode')
            themeToggle.checked = false
            themeLabel.textContent = '亮色模式'
          }

          // 添加主题切换事件监听器
          themeToggle.addEventListener('change', function () {
            if (this.checked) {
              document.body.classList.add('dark-mode')
              setCookie('theme_datetime', 'dark', 30)
              themeLabel.textContent = '暗黑模式'
            } else {
              document.body.classList.remove('dark-mode')
              setCookie('theme_datetime', 'light', 30)
              themeLabel.textContent = '亮色模式'
            }
          })
        }

        // Cookie 操作函数
        function setCookie(name, value, days) {
          const expires = new Date()
          expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000)
          document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`
        }

        function getCookie(name) {
          const cookieName = `${name}=`
          const cookies = document.cookie.split(';')

          for (let i = 0; i < cookies.length; i++) {
            let cookie = cookies[i].trim()
            if (cookie.indexOf(cookieName) === 0) {
              return cookie.substring(cookieName.length, cookie.length)
            }
          }

          return null
        }

        // 初始化日历
        function initCalendar() {
          updateCalendar()
          updateTimeCalendar()
          updateSelectedDateDisplay()

          // 添加事件监听器
          document.getElementById('prev-month').addEventListener('click', () => {
            selectedDate.setMonth(selectedDate.getMonth() - 1)
            updateCalendar()
          })

          document.getElementById('next-month').addEventListener('click', () => {
            selectedDate.setMonth(selectedDate.getMonth() + 1)
            updateCalendar()
          })

          // 标签切换
          document.querySelectorAll('.tab').forEach((tab) => {
            tab.addEventListener('click', () => {
              document.querySelectorAll('.tab').forEach((t) => t.classList.remove('active'))
              document.querySelectorAll('.tab-content').forEach((t) => t.classList.remove('active'))

              tab.classList.add('active')
              document.getElementById(`${tab.dataset.tab}-tab`).classList.add('active')
            })
          })

          // 时间选择控件
          document.getElementById('hour-up').addEventListener('click', () => {
            selectedHour = (selectedHour + 1) % 24
            document.getElementById('hour').value = String(selectedHour).padStart(2, '0')
            updateSelectedDateDisplay()
          })

          document.getElementById('hour-down').addEventListener('click', () => {
            selectedHour = (selectedHour - 1 + 24) % 24
            document.getElementById('hour').value = String(selectedHour).padStart(2, '0')
            updateSelectedDateDisplay()
          })

          document.getElementById('minute-up').addEventListener('click', () => {
            selectedMinute = (selectedMinute + 1) % 60
            document.getElementById('minute').value = String(selectedMinute).padStart(2, '0')
            updateSelectedDateDisplay()
          })

          document.getElementById('minute-down').addEventListener('click', () => {
            selectedMinute = (selectedMinute - 1 + 60) % 60
            document.getElementById('minute').value = String(selectedMinute).padStart(2, '0')
            updateSelectedDateDisplay()
          })

          // 输入框变化
          document.getElementById('hour').addEventListener('change', function () {
            let value = parseInt(this.value) || 0
            selectedHour = Math.min(23, Math.max(0, value))
            this.value = String(selectedHour).padStart(2, '0')
            updateSelectedDateDisplay()
          })

          document.getElementById('minute').addEventListener('change', function () {
            let value = parseInt(this.value) || 0
            selectedMinute = Math.min(59, Math.max(0, value))
            this.value = String(selectedMinute).padStart(2, '0')
            updateSelectedDateDisplay()
          })
        }

        // 按钮事件 - 确认选择
        document.getElementById('btn-confirm').addEventListener('click', () => {
          alert(
            `已选择: ${formatDate(selectedDate)} ${String(selectedHour).padStart(2, '0')}:${String(selectedMinute).padStart(2, '0')}`
          )
        })

        // 按钮事件 - 重置
        document.getElementById('btn-cancel').addEventListener('click', () => {
          selectedDate = new Date()
          updateCalendar()
          updateTimeCalendar()
          updateSelectedDateDisplay()
        })

        // 更新日历显示
        function updateCalendar() {
          const year = selectedDate.getFullYear()
          const month = selectedDate.getMonth()

          document.getElementById('current-month').textContent = `${year}年${month + 1}月`

          const firstDay = new Date(year, month, 1)
          const lastDay = new Date(year, month + 1, 0)
          const daysInMonth = lastDay.getDate()
          const startDay = firstDay.getDay() // 0 (Sunday) to 6 (Saturday)

          const calendarDays = document.getElementById('calendar-days')
          calendarDays.innerHTML = ''

          // 填充上个月的天数
          const prevMonthLastDay = new Date(year, month, 0).getDate()
          for (let i = 0; i < startDay; i++) {
            const dayElement = document.createElement('div')
            dayElement.textContent = prevMonthLastDay - startDay + i + 1
            dayElement.classList.add('other-month')
            calendarDays.appendChild(dayElement)
          }

          // 填充当前月的天数
          const today = new Date()
          for (let i = 1; i <= daysInMonth; i++) {
            const dayElement = document.createElement('div')
            dayElement.textContent = i

            // 检查是否是今天
            if (
              year === today.getFullYear() &&
              month === today.getMonth() &&
              i === today.getDate()
            ) {
              dayElement.classList.add('today')
            }

            // 检查是否是选中的日期
            if (
              i === selectedDate.getDate() &&
              year === selectedDate.getFullYear() &&
              month === selectedDate.getMonth()
            ) {
              dayElement.classList.add('selected')
            }

            dayElement.addEventListener('click', () => {
              // 移除之前选中的日期
              document.querySelectorAll('.days div.selected').forEach((el) => {
                el.classList.remove('selected')
              })

              // 选中当前点击的日期
              dayElement.classList.add('selected')

              // 更新选中的日期
              selectedDate = new Date(year, month, i)
              updateSelectedDateDisplay()
            })

            calendarDays.appendChild(dayElement)
          }

          // 填充下个月的天数
          const totalCells = 42 // 6行7列
          const remainingCells = totalCells - (startDay + daysInMonth)
          for (let i = 1; i <= remainingCells; i++) {
            const dayElement = document.createElement('div')
            dayElement.textContent = i
            dayElement.classList.add('other-month')
            calendarDays.appendChild(dayElement)
          }
        }

        // 更新时间显示
        function updateTimeCalendar() {
          const Hour = selectedDate.getHours()
          const Minute = selectedDate.getMinutes()

          selectedHour = Hour
          selectedMinute = Minute

          document.getElementById('hour').value = `${String(Hour).padStart(2, '0')}`
          document.getElementById('minute').value = `${String(Minute).padStart(2, '0')}`
        }

        // 更新选中的日期显示
        function updateSelectedDateDisplay() {
          const dateStr = formatDate(selectedDate)
          const timeStr = `${String(selectedHour).padStart(2, '0')}:${String(selectedMinute).padStart(2, '0')}`
          document.getElementById('selected-date').textContent = `当前选择: ${dateStr} ${timeStr}`
        }

        // 格式化日期
        function formatDate(date) {
          const year = date.getFullYear()
          const month = date.getMonth() + 1
          const day = date.getDate()
          return `${year}年${month}月${day}日`
        }

        // 初始化
        initTheme()
        initCalendar()
      })
    </script>
  </body>
</html>

预览地址: https://preview.yunbimo.com/0b7e4185-833f-4a0b-b8ef-b9ecdf591ad3