尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

freeCodeCamp 每日编程挑战 88 Weekday Finder 解析:用 `Date.UTC` 与 `getUTCDay` 写出时区无关的“星期几”计算

freeCodeCamp 每日编程挑战 88 Weekday Finder 解析:用 `Date.UTC` 与 `getUTCDay` 写出时区无关的“星期几”计算 freeCodeCamp 每日编程挑战 88 Weekday Finder 解析用Date.UTC与getUTCDay写出时区无关的“星期几”计算【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp本篇技术指南以 freeCodeCamp 开源仓库中 Challenge 88: Weekday Finder 这道 JavaScript 挑战题为骨架完整还原题目要求、5 组自动化测试hints与官方参考实现并逐行拆解“字符串日期 → 星期几”的底层原理。读完你将掌握Date.UTC构造、getUTCDay索引映射、0 起始月份等易错点能写出在任何时区下结果都稳定一致的日期换算代码同时理解这道题在 freeCodeCamp Daily Coding Challenge 体系365 道连续 JavaScript 题中所处的位置与周边实现。挑战背景这是“每日一题”体系的第 88 题该题目文件位于 daily-coding-challenges-javascript 代码块下。从 代码块元数据 可以看到这是一个完整的长序列共 365 道连续编号的 JavaScript 挑战第 1 题 Vowel Balance 到第 365 题 The Last Challenge: Bucket Fill 3第 88 题即为本文讲解的 Weekday Finder。文件头部 frontmatter 信息字段值含义id68ee9e3066cfd4eb2328e8a7全局唯一标识与 代码块 JSON 中 Challenge 88 的id一致titleChallenge 88: Weekday Finder题目显示名challengeType28题目类型码见下文dashedNamechallenge-88URL / 文件名规范化名称其中challengeType: 28并非随意数字。在 packages/shared/src/config/challenge-types.ts 中定义dailyChallengeJs 28、dailyChallengePy 29也就是说这道题被平台标记为JavaScript 每日编程挑战daily coding challenge。该文件同时声明[dailyChallengeJs]: classic按 classic 经典编辑器布局渲染[dailyChallengeJs]: tests验证方式走自动化测试断言语言映射为javascript。与此呼应代码块元数据中的helpCategory: JavaScript、usesMultifileEditor: true与disableLoopProtectTests: true也都说明它属于实际可运行、可自动判分的一类题目。前端布局组件 desktop-layout.tsx 会按dailyChallengeJs/dailyChallengePy分支处理多文件编辑器的显示印证了这套类型码在真实渲染链路中的消费方式。题目描述与输入输出约定Given a string date in the format YYYY-MM-DD, return the day of the week.即实现一个函数接收形如YYYY-MM-DD的日期字符串返回对应的星期几。输出的合法取值集合是完整的一周七天首字母大写、全称英文SundayMondayTuesdayWednesdayThursdayFridaySaturday题目额外强调一条硬性约束Be sure to ignore time zones务必忽略时区。这一点是整道题的灵魂——只根据“年月日”三个数字本身计算星期任何本地时区偏移、夏令时都不允许影响结果。它意味着不能把字符串丢给“本地时间”相关的 API 后听天由命而必须用不依赖运行环境时区的UTC路径来计算。自动化测试hints5 个覆盖不同年代的断言题目的--hints--部分是平台判定代码正确性的唯一标准共 5 个assert.equal断言全部针对测试点getWeekday(...)。这些用例刻意挑选了跨度极大的年份用来验证算法对普通实现常见“年份边界”问题的处理调用期望返回值getWeekday(2025-11-06)ThursdaygetWeekday(1999-12-31)FridaygetWeekday(1111-11-11)SaturdaygetWeekday(2112-12-21)WednesdaygetWeekday(2345-10-01)Monday以2025-11-06为例题目给出的断言等价于assert.equal(getWeekday(2025-11-06), Thursday);覆盖思路值得注意近代日期2025-11-06验证常规路径千禧年临界1999-12-31周末与年份交界验证跨年与世纪边界超远年代1111-11-11、2112-12-21、2345-10-01验证实现没有隐含“只能处理近现代日期”的上限假设——这正是许多依赖new Date(year, month, day)或字符串解析的写法容易出问题的地方。若用暴力穷举法在本地对照公历校验这 5 个用例实际覆盖了星期循环7 天一循环内彼此不重合的 5 个不同星期值加上种子示例本身能够有效防止“硬编码一两个正确答案”之类的取巧实现。起点代码seed需要补全的骨架题目给出的初始模板非常简单几乎只定义了函数签名与一个占位返回值function getWeekday(dateString) { return dateString; }学习者的任务就是把return dateString这一行占位逻辑替换成真正的“解析日期 → 计算星期 → 返回星期名”实现。注意参数名dateString提示了输入一定是字符串而非Date对象这是后续实现的重要前提。官方参考实现逐行拆解--solutions--区块提供了 freeCodeCamp 官方给出的解法仅 6 行核心代码却精准命中了题目的每一个要求function getWeekday(dateString) { const days [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]; const [year, month, day] dateString.split(-).map(Number); const date new Date(Date.UTC(year, month - 1, day)); return days[date.getUTCDay()]; }逐行剖析如下。第一步建立“索引 → 星期名”映射表const days [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday];数组下标从 0 开始正好对应 JavaScriptDateAPI 中getUTCDay()的返回值约定0 表示 Sunday周日1 表示 Monday周一依此类推6 表示 Saturday周六。把枚举直接放进数组是最简洁的查表法也天然规避了写一堆switch/case的冗长。第二步拆分并转换字符串的三个分量const [year, month, day] dateString.split(-).map(Number);输入是YYYY-MM-DD格式字符串用split(-)得到[YYYY, MM, DD]三个字符串片段再.map(Number)统一转为数字。数组解构把它们分别绑定到year、month、day三个变量。这里有两层易错点Number(2025)这类转换不会受前导零影响11→11但如果你忘记.map(Number)后续Date.UTC收到的是字符串参数——Date.UTC内部会做隐式转换多数情况下仍能工作只是类型上不严谨、可读性差且容易在字符串拼接类代码中埋雷。第三步用Date.UTC构造“无时区”的日期对象const date new Date(Date.UTC(year, month - 1, day));这是全题最关键的一行对应题目“忽略时区”的要求Date.UTC(year, monthIndex, day)以UTC协调世界时语义构造一个毫秒时间戳全程不查操作系统本地时区、不做任何偏移换算从而保证在纽约、北京、伦敦等任何环境下结果一致Date.UTC的month参数同样遵循 JavaScript月份从 0 开始的约定0 January所以传month - 1将题目中的1111 月映射为内部索引10。忘记减 1 会导致月份整体偏移一个月是这类题目最高频的“差一错误”off-by-one1111、2112、2345等远年代年份之所以能正确参与计算是因为Date.UTC对 099 之外的年份不做1900 year式的特殊加码而测试用例如题目所示恰好都绕开了 099 陷阱。第四步读取“星期索引”并查表返回return days[date.getUTCDay()];构造出的date是Date实例取星期时使用getUTCDay()而非getDay()getDay()返回本地时区下的星期索引会随运行环境时区变化而产生一天偏差getUTCDay()严格返回 UTC 语义下的星期索引0–6与上一步的 UTC 构造方式完全配套形成“构造与读取都走 UTC”的闭环彻底兑现“忽略时区”的约束。深入原理为什么不能直接用字符串构造Date许多初学者会写出这样的“偷懒”版本// 反例 function getWeekday(dateString) { const date new Date(dateString); const days [Sunday, ..., Saturday]; return days[date.getDay()]; }它至少在两个层面站不住脚解析语义不一致ECMAScript 规范对“仅含日期的字符串”date-only form如2025-11-06要求按 UTC 解释但许多开发者并不清楚这一隐含规则一旦代码库演进为解析含时间的字符串或运行环境差异导致实现偏差结果可能被本地时区“拖走”一天。读取时区不对称即便构造端按 UTC 解析若读取端仍用getDay()在 UTC 早于当地午夜如美国时区时本地日期可能与 UTC 日期错位一天直接返回错误的星期。官方解法的价值正在于把“构造”与“读取”显式、对称地统一到 UTC 坐标系Date.UTCgetUTCDay从而在任何时区下输出都一致。这也是工程上处理“纯日历日期”不关心时刻、只关心年月日时推荐的心智模型。这种“把日期当纯日历值处理”的策略在整个仓库中是一以贯之的。例如客户端工具 client/src/components/daily-coding-challenge/helpers.ts 在校验MM-DD字符串时就用new Date(Date.UTC(2000, month - 1, day))来构造并注释说明了原因2000is a leap year, so it keeps Feb 29 instead of rolling it over.Date.UTCsilently rolls over out-of-range values - this catches that.也就是说仓库在处理每日挑战相关的日期逻辑时同样依赖Date.UTCgetUTCMonth()/getUTCDate()组合来规避本地时区与“非法日期被自动进位”两类问题——与本挑战的解题思路属于同一套方法论。边界条件与延伸思考闰年的 2 月 29 日题目输入严格遵循YYYY-MM-DD与真实日历Date.UTC遇到不存在的日期如2023-02-29会“静默进位”到 3 月 1 日。官方解法假定输入合法故无需处理但若做健壮性扩展可参考 helpers.ts 的做法——构造后用getUTCMonth()、getUTCDate()回读校验是否发生进位。年份 0–99 陷阱new Date(0, 0, 1)或Date.UTC(0, ...)会把0映射为1900。本挑战的测试数据刻意避开了这一区间但若输入来自用户是值得防御的场景。不引入第三方库该题只需标准库 API 即可完成这也是它被设计为入门级“每日题”的原因——split、Date.UTC、getUTCDay、数组查表四个知识点即可串起完整答案。验证方法本地运行测试由于--hints--中的断言均为纯函数式assert.equal不依赖浏览器 DOM 与平台登录状态你完全可以在本地 Node.js 环境验证你的实现。把函数定义与断言放入同一文件后执行即可例如node weekday-finder.test.js等价于将官方解法与全部 5 个断言合并在一个脚本中运行任何断言不通过都会得到明确的差异输出。在 freeCodeCamp 平台上这一挑战的“运行测试”按钮执行的正是 测试断言 中这类assert逻辑。从一道题看整个 Daily Coding Challenge 产品链路Weekday Finder 只是 freeCodeCamp 每日编程挑战产品线的一个切片。若想把它放进更大的工程上下文理解仓库中可继续追踪的路径包括代码块顺序定义确认第 88 题在 365 道题中的编号位置与前后相邻题目挑战类型定义理解challengeType: 28对应的dailyChallengeJs及其渲染/验证行为API 每日挑战路由平台按日期/date/:date、/today、/month/:month等从数据库分发每日挑战元信息说明“每天一道”的调度由服务端按美国中部时区日期控制客户端每日挑战组件展示学习地图上“今日挑战”入口与日历归档入口客户端日期工具展示了本项目处理日期字符串时对Date.UTC/ 时区语义的严谨态度。综上Challenge 88 Weekday Finder 是一道“小而深”的日期处理题表面上只需返回星期几实质考察的是对 JavaScriptDate对象 UTC 语义、月份 0 起始约定、getUTCDay返回值映射三个关键点的综合掌握。把官方 6 行解法吃透你就同时掌握了一套可迁移到任何“纯日历日期计算”场景如工作日推算、倒计时、排期系统的通用范式。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表