HTML5 日期输入框扩展:支持年积日(YYYYddd)格式的日历选择器

浅丽吖_4230

浅丽吖_4230

2026-07-09

787人浏览

原创

本文介绍如何基于原生 html5 日期输入逻辑,构建一个可切换“月日”与“年积日(day of year)”显示模式的自定义日历组件,兼顾标准兼容性与卫星数据处理需求。

本文介绍如何基于原生 html5 日期输入逻辑,构建一个可切换“月日”与“年积日(day of year)”显示模式的自定义日历组件,兼顾标准兼容性与卫星数据处理需求。

在遥感、气象及地球观测领域,卫星数据常以 YYYYddd 格式标注时间(如 2024120 表示 2024 年第 120 天,即 4 月 29 日),这种“年积日”(Day of Year, DOY)表示法比传统 YYYY-MM-DD 更便于序列化处理与跨年计算。然而,原生 仅支持 ISO 8601 格式(YYYY-MM-DD),无法直接显示或输入 YYYYddd。本文提供一种轻量、可嵌入、符合 HTML5 语义习惯的解决方案:不替换原生输入框,而是为其配套构建一个功能对齐 NOAA 网站风格的自定义日历弹窗,并支持一键切换“月日视图”与“年积日视图”。

核心设计思路

  • 解耦渲染与数据:保留原生 作为表单提交和无障碍访问的基础,同时通过 JavaScript 动态绑定自定义日历面板;
  • 双模式日历:点击“Toggle Day Number View”按钮,表格单元格从显示 1–31 切换为显示对应日期在当年的序号(1–365/366);
  • 精准 DOY 计算:采用时间戳差值法(new Date(year, month, day) - new Date(year, 0, 0))避免闰年判断误差,确保 getDayNumberOfYear() 结果 100% 准确;
  • 响应式交互:支持年/月导航、自动更新标题、空单元格占位,保持视觉一致性。

以下为完整可运行代码(含内联样式与脚本,开箱即用):

html-ppt-to-pdf
html-ppt-to-pdf

将使用 `

` 约定的 HTML 幻灯片转换为高保真、矢量文本 PDF(使用 Playwright + Chromium 原生 PDF 功能)。

下载


    <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>DOY-Aware Calendar Picker</title><style>
        #calcontainer {
            position: relative;
            margin: 20px 0;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        }
        #calendar {
            border-collapse: collapse;
            width: 100%;
            margin-top: 12px;
        }
        #calendar th, #calendar td {
            border: 1px solid #e0e0e0;
            padding: 10px 6px;
            text-align: center;
            vertical-align: middle;
        }
        #calendar th {
            background-color: #f8f9fa;
            font-weight: 600;
            color: #495057;
        }
        .calendar-row { height: 48px; }
        button {
            margin: 4px;
            padding: 6px 12px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 0.9em;
        }
        button:hover { background: #0056b3; }
        #cp_monthYear {
            font-weight: bold;
            margin: 0 16px;
            display: inline-block;
        }
    </style><!-- 原生日期输入框(保留标准表单能力) --><input type="date" id="dateInput" style="margin: 0 20px;"><div id="calcontainer">
        <!-- 导航栏 -->
        <div>
            <button id="cp_prevYear" onclick="changeYear(-1)">< 上一年</button>
            <button id="cp_prevMonth" onclick="changeMonth(-1)">< 上一月</button>
            <span id="cp_monthYear"></span>
            <button id="cp_nextMonth" onclick="changeMonth(1)">下一月 ></button>
            <button id="cp_nextYear" onclick="changeYear(1)">下一年 ></button>
        </div>
        <div style="margin-top: 8px;">
            <button onclick="toggleDayNumberView()">切换年积日视图</button>
        </div>
        <!-- 日历主体 -->
        <table id="calendar">
<thead><tr>
<th>日</th>
<th>一</th>
<th>二</th>
<th>三</th>
<th>四</th>
<th>五</th>
<th>六</th>
                </tr></thead>
<tbody></tbody>
</table>
</div>

    <script>
        let currentYear = new Date().getFullYear();
        let currentMonth = new Date().getMonth(); // 0-based
        let showDayNumbers = false;
        const dateInput = document.getElementById('dateInput');

        function populateCalendar() {
            const monthYearDisplay = document.getElementById('cp_monthYear');
            const tbody = document.querySelector('#calendar tbody');
            tbody.innerHTML = '';

            const firstDay = new Date(currentYear, currentMonth, 1);
            const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
            const startDayOfWeek = firstDay.getDay(); // 0=Sun, 6=Sat

            // 更新标题
            monthYearDisplay.textContent = 
                `${firstDay.toLocaleDateString('zh-CN', { month: 'long' })} ${currentYear}`;

            // 插入前置空单元格(补齐周日开始)
            for (let i = 0; i < startDayOfWeek; i++) {
                tbody.insertAdjacentHTML('beforeend', '<td>');
            }

            // 插入当月日期单元格
            let dayNum = showDayNumbers 
                ? getDayNumberOfYear(currentYear, currentMonth, 1) 
                : 1;

            for (let day = 1; day <= daysInMonth; day++) {
                const cell = document.createElement('td');
                cell.textContent = showDayNumbers ? dayNum++ : day;
                cell.addEventListener('click', () => selectDate(day));
                tbody.appendChild(cell);
            }

            // 补齐末尾空单元格(保证 6 行)
            const totalCells = startDayOfWeek + daysInMonth;
            const remaining = (7 - totalCells % 7) % 7;
            for (let i = 0; i < remaining; i++) {
                tbody.insertAdjacentHTML('beforeend', '<td>');
            }
        }

        function selectDate(day) {
            const selectedDate = new Date(currentYear, currentMonth, day);
            const isoStr = selectedDate.toISOString().split('T')[0]; // YYYY-MM-DD
            dateInput.value = isoStr;
            // 可选:触发 input/change 事件以通知框架
            dateInput.dispatchEvent(new Event('input', { bubbles: true }));
            dateInput.dispatchEvent(new Event('change', { bubbles: true }));
        }

        function changeMonth(delta) {
            currentMonth += delta;
            if (currentMonth < 0) {
                currentMonth = 11;
                currentYear--;
            } else if (currentMonth > 11) {
                currentMonth = 0;
                currentYear++;
            }
            populateCalendar();
        }

        function changeYear(delta) {
            currentYear += delta;
            populateCalendar();
        }

        function toggleDayNumberView() {
            showDayNumbers = !showDayNumbers;
            populateCalendar();
        }

        function getDayNumberOfYear(year, month, day) {
            const date = new Date(year, month, day);
            const yearStart = new Date(year, 0, 1);
            const diffMs = date.getTime() - yearStart.getTime();
            return Math.floor(diffMs / (1000 * 60 * 60 * 24)) + 1;
        }

        // 初始化并绑定输入框同步(可选增强)
        dateInput.addEventListener('change', () => {
            const d = new Date(dateInput.value);
            if (!isNaN(d.getTime())) {
                currentYear = d.getFullYear();
                currentMonth = d.getMonth();
                populateCalendar();
            }
        });

        populateCalendar();
    </script>

关键注意事项

  • 无障碍与兼容性:原生 仍存在,确保移动端唤起系统日历、屏幕阅读器识别及表单验证正常工作;
  • ⚠️ 样式隔离建议:生产环境请将 CSS 提取至外部文件,并使用 CSS Modules 或 Shadow DOM 避免全局污染;
  • ? 双向同步增强:当前示例已实现“日历选中 → 输入框更新”,如需反向同步(输入框修改 → 日历跳转),可在 input 事件监听中解析 YYYY-MM-DD 并重置 currentYear/currentMonth;
  • ? 模块化封装:推荐将上述逻辑封装为 Web Component(如 doy-calendar 自定义元素),便于复用与维护。

该方案不依赖第三方库,纯原生技术栈实现,既满足科研场景对 YYYYddd 的高频操作需求,又坚守 Web 标准底线——让专业工具回归语义化、可访问、可持续演进的 HTML 生态。

前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

html5 html yy

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
html版权符号
html版权符号

html版权符号是“©”,可以在html源文件中直接输入或者从word中复制粘贴过来,php中文网还为大家带来html的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.14

5015

7

html在线编辑器
html在线编辑器

html在线编辑器是用于在线编辑的工具,编辑的内容是基于HTML的文档。它经常被应用于留言板留言、论坛发贴、Blog编写日志或等需要用户输入普通HTML的地方,是Web应用的常用模块之一。php中文网为大家带来了html在线编辑器的相关教程、以及相关文章等内容,供大家免费下载使用。

2023.06.21

2932

4

html网页制作
html网页制作

html网页制作是指使用超文本标记语言来设计和创建网页的过程,html是一种标记语言,它使用标记来描述文档结构和语义,并定义了网页中的各种元素和内容的呈现方式。本专题为大家提供html网页制作的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.31

2570

5

html空格
html空格

html空格是一种用于在网页中添加间隔和对齐文本的特殊字符,被用于在网页中插入额外的空间,以改变元素之间的排列和对齐方式。本专题为大家提供html空格的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.01

2619

5

html是什么
html是什么

HTML是一种标准标记语言,用于创建和呈现网页的结构和内容,是互联网发展的基石,为网页开发提供了丰富的功能和灵活性。本专题为大家提供html相关的各种文章、以及下载和课程。

2023.08.11

4579

6

html字体大小怎么设置
html字体大小怎么设置

在网页设计中,字体大小的选择是至关重要的。合理的字体大小不仅可以提升网页的可读性,还能够影响用户对网页整体布局的感知。php中文网将介绍一些常用的方法和技巧,帮助您在HTML中设置合适的字体大小。

2023.08.11

2561

3

html转txt
html转txt

html转txt的方法有使用文本编辑器、使用在线转换工具和使用Python编程。本专题为大家提供html转txt相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.31

2349

3

html文本框代码怎么写
html文本框代码怎么写

html文本框代码:1、单行文本框【<input type="text" style="height:..;width:..;" />】;2、多行文本框【textarea style=";height:;"></textare】。

2023.09.01

2148

6

HTML嵌入CSS样式的方法
HTML嵌入CSS样式的方法

HTML嵌入CSS样式的方法有内联样式、内部样式表和外部样式表。本专题为大家提供CSS样式相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.20

2128

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 10.6万人学习

HTML+CSS基础与实战
HTML+CSS基础与实战

共132课时 | 18.3万人学习

前端开发(基础+实战项目合集)
前端开发(基础+实战项目合集)

共60课时 | 6.2万人学习