[网站模板]日期时间选择器插件 - 开发者工具,响应式,支持暗黑模式,html纯静态源码
日期时间选择器插件:提供日期选择和时间选择功能
双标签切换:支持日期选择和时间选择两个独立面板
交互式日历:可切换月份,点击选择日期,显示今日标记
时间调节控件:通过上下按钮或直接输入调整小时和分钟
暗黑/亮色模式:右上角一键切换,保存用户偏好到 Cookie
响应式设计:适配手机和桌面设备
核心功能:日期选择(日历面板),时间选择(小时/分钟调节),确认选择(弹窗显示结果),重置(恢复当前时间)
适用场景:开发者工具、表单组件、后台管理系统
html
<!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"><</button>
<h2 id="current-month"></h2>
<button id="next-month">></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