字符串是否为 ISO 格式日期

JavaScriptJavaScriptBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在这个实验中,我们将探讨如何判断一个给定的字符串是否为简化扩展 ISO 格式(ISO 8601)的有效日期字符串。我们将使用 Date 构造函数及其相关方法,从字符串创建一个 Date 对象并检查其有效性。在实验结束时,你将更好地理解如何在 JavaScript 中处理日期,以及如何使用 ISO 格式验证日期。

理解 ISO 日期格式和 JavaScript 日期对象

在开始编码之前,让我们先了解一下 ISO 8601 日期格式是什么,以及 JavaScript 如何处理日期。

ISO 8601 日期格式

ISO 8601 格式是一种表示日期和时间的国际标准。简化扩展 ISO 格式如下所示:

YYYY-MM-DDTHH:mm:ss.sssZ

其中:

  • YYYY 表示年份(四位数)
  • MM 表示月份(两位数)
  • DD 表示日期(两位数)
  • T 是分隔日期和时间的文字字符
  • HH 表示小时(两位数)
  • mm 表示分钟(两位数)
  • ss 表示秒数(两位数)
  • sss 表示毫秒(三位数)
  • Z 表示协调世界时(UTC)时区(祖鲁时间)

例如,2023-05-12T14:30:15.123Z 表示 2023 年 5 月 12 日下午 2 点 30 分 15.123 秒(UTC 时间)。

JavaScript 日期对象

JavaScript 提供了一个内置的 Date 对象,用于处理日期和时间。当你创建一个新的 Date 对象时,可以向其传递一个 ISO 格式的字符串:

const date = new Date("2023-05-12T14:30:15.123Z");

让我们打开终端,练习使用日期对象:

  1. 通过点击 WebIDE 顶部的“终端”菜单打开终端。
  2. 输入 node 并按回车键,启动 Node.js 交互式 shell。
  3. 创建一个表示当前时间的新日期对象:
const now = new Date();
console.log(now);
node-prompt
  1. 将这个日期对象转换为 ISO 字符串:
const isoString = now.toISOString();
console.log(isoString);

你应该会看到类似于以下的输出:

2023-05-12T14:30:15.123Z
  1. 从 ISO 字符串创建一个日期对象:
const dateFromIso = new Date("2023-05-12T14:30:15.123Z");
console.log(dateFromIso);
node-prompt

这展示了 JavaScript 如何解析 ISO 格式的字符串并从中创建日期对象。

创建一个函数来验证 ISO 格式的日期字符串

在这一步中,我们将创建一个 JavaScript 函数,用于检查给定的字符串是否为有效的 ISO 8601 格式。

创建验证函数

让我们为 ISO 日期验证器创建一个新的 JavaScript 文件:

  1. 在 WebIDE 中,点击左侧侧边栏的“资源管理器”图标。
  2. 在文件资源管理器中右键单击,选择“新建文件”。
  3. 将文件命名为 isISODate.js 并按回车键。
  4. 在文件中添加以下代码:
/**
 * Checks if a string is a valid ISO 8601 formatted date string
 * @param {string} val - The string to check
 * @return {boolean} - Returns true if the string is in ISO format, false otherwise
 */
const isISOString = (val) => {
  // Create a Date object from the input string
  const d = new Date(val);

  // Check if the date is valid (not NaN) and if the ISO string matches the original
  return !Number.isNaN(d.valueOf()) && d.toISOString() === val;
};

// Export the function so we can use it elsewhere
module.exports = isISOString;

让我们来分析一下这个函数的工作原理:

  1. new Date(val) 从输入字符串创建一个日期对象。
  2. d.valueOf() 返回数字时间戳值(自 1970 年 1 月 1 日以来的毫秒数)。
  3. Number.isNaN(d.valueOf()) 检查日期是否无效(NaN 表示“非数字”)。
  4. d.toISOString() === val 验证将日期对象转换回 ISO 字符串是否与原始输入匹配。

测试我们的函数

现在,让我们创建一个简单的测试文件来测试我们的函数:

  1. 创建另一个名为 testISO.js 的文件。
  2. 添加以下代码:
// Import our isISOString function
const isISOString = require("./isISODate");

// Test with a valid ISO formatted date
console.log("Testing a valid ISO date:");
console.log("2020-10-12T10:10:10.000Z");
console.log("Result:", isISOString("2020-10-12T10:10:10.000Z"));
console.log();

// Test with an invalid format
console.log("Testing a non-ISO date:");
console.log("2020-10-12");
console.log("Result:", isISOString("2020-10-12"));
  1. 使用 Node.js 运行测试文件:
node testISO.js

你应该会看到类似于以下的输出:

Testing a valid ISO date:
2020-10-12T10:10:10.000Z
Result: true

Testing a non-ISO date:
2020-10-12
Result: false

这表明我们的函数能够正确识别 "2020-10-12T10:10:10.000Z" 是有效的 ISO 格式日期,而 "2020-10-12" 不是。

使用各种日期格式进行测试

既然我们已经有了基本的验证函数,那就用不同的日期格式来测试它,以了解它在各种输入下的表现。

创建测试套件

让我们创建一个全面的测试套件,来检查不同的日期格式:

  1. 创建一个名为 dateTester.js 的新文件。
  2. 添加以下代码:
// Import our isISOString function
const isISOString = require("./isISODate");

// Function to test different date strings
function testDate(description, dateString) {
  console.log(`Testing: ${description}`);
  console.log(`Input: "${dateString}"`);
  console.log(`Is ISO Format: ${isISOString(dateString)}`);
  console.log("-----------------------");
}

// Valid ISO date examples
testDate("Standard ISO date with timezone Z", "2023-05-12T14:30:15.123Z");
testDate("ISO date with zero milliseconds", "2020-10-12T10:10:10.000Z");

// Invalid or non-ISO format examples
testDate("Date only (no time component)", "2023-05-12");
testDate("Date and time without milliseconds", "2023-05-12T14:30:15Z");
testDate(
  "Date with time zone offset instead of Z",
  "2023-05-12T14:30:15+01:00"
);
testDate("Invalid date (month 13 does not exist)", "2023-13-12T14:30:15.123Z");
testDate("Non-date string", "Hello World");
  1. 在终端中运行测试套件:
node dateTester.js

你应该会看到输出,显示哪些字符串是有效的 ISO 日期,哪些不是。

理解测试结果

让我们分析一下每个测试用例有效或无效的原因:

  1. 2023-05-12T14:30:15.123Z —— 这个是有效的,因为它遵循了完整的 ISO 8601 格式,并带有 UTC 时区指示符(Z)。

  2. 2020-10-12T10:10:10.000Z —— 这个也是有效的,其中毫秒数明确设置为 000。

  3. 2023-05-12 —— 这是一个有效的日期,但不是 ISO 格式,因为它缺少时间部分。

  4. 2023-05-12T14:30:15Z —— 这看起来像是 ISO 格式,但缺少严格 ISO 格式中必需的毫秒数。

  5. 2023-05-12T14:30:15+01:00 —— 这里使用了时区偏移量(+01:00)而不是 'Z'。虽然根据 ISO 8601 这是有效的,但我们的函数要求的是 toISOString() 方法生成的精确格式,该格式始终使用 'Z'。

  6. 2023-13-12T14:30:15.123Z —— 这是一个无效的日期(不存在 13 月),因此 new Date() 会创建一个无效的日期对象。

  7. Hello World —— 这根本不是一个日期,所以 new Date() 会创建一个无效的日期对象。

我们的验证函数特别检查了两个条件:

  1. 字符串必须能解析为有效的日期(不是 NaN)。
  2. 当该日期转换回 ISO 字符串时,必须与原始输入完全匹配。

这种方法确保我们验证的是 JavaScript 的 toISOString() 方法生成的精确 ISO 格式。

处理边界情况并改进我们的函数

在这最后一步中,我们将改进 isISOString 函数,以处理边界情况并使其更加健壮。

常见的边界情况

在实际应用中验证数据时,你需要处理各种意外输入。让我们来看看一些边界情况:

  1. 空字符串
  2. 非字符串值(null、undefined、数字、对象)
  3. 不同的时区表示法

增强我们的函数

让我们更新 isISODate.js 文件来处理这些边界情况:

  1. 在 WebIDE 中打开 isISODate.js 文件。
  2. 用这个改进后的版本替换现有的代码:
/**
 * Checks if a string is a valid ISO 8601 formatted date string
 * @param {string} val - The string to check
 * @return {boolean} - Returns true if the string is in ISO format, false otherwise
 */
const isISOString = (val) => {
  // Check if input is a string
  if (typeof val !== "string") {
    return false;
  }

  // Check if string is empty
  if (val.trim() === "") {
    return false;
  }

  try {
    // Create a Date object from the input string
    const d = new Date(val);

    // Check if the date is valid and if the ISO string matches the original
    return !Number.isNaN(d.valueOf()) && d.toISOString() === val;
  } catch (error) {
    // If any error occurs during validation, return false
    return false;
  }
};

// Export the function
module.exports = isISOString;

这个改进后的函数现在可以:

  1. 在处理之前检查输入是否为字符串。
  2. 处理空字符串。
  3. 使用 try-catch 块来处理可能发生的任何错误。
  4. 仍然执行我们的核心验证逻辑。

测试我们改进后的函数

让我们创建一个最终的测试文件,用边界情况来验证我们改进后的函数:

  1. 创建一个名为 edgeCaseTester.js 的新文件。
  2. 添加以下代码:
// Import our improved isISOString function
const isISOString = require("./isISODate");

// Function to test and display results
function testCase(description, value) {
  console.log(`Testing: ${description}`);
  console.log(`Input: ${value === "" ? "(empty string)" : value}`);
  console.log(`Type: ${typeof value}`);
  console.log(`Is ISO Format: ${isISOString(value)}`);
  console.log("-----------------------");
}

// Test with various edge cases
testCase("Valid ISO date", "2023-05-12T14:30:15.123Z");
testCase("Empty string", "");
testCase("Null value", null);
testDate("Undefined value", undefined);
testCase("Number value", 12345);
testCase("Object value", {});
testCase("Current date as ISO string", new Date().toISOString());
  1. 运行测试文件:
node edgeCaseTester.js

实际应用

在实际应用中,我们的 isISOString 函数可以用于以下场景:

  1. 验证日期字段中的用户输入。
  2. 检查从外部 API 接收到的日期。
  3. 确保数据库中日期格式的一致性。
  4. 在处理数据之前进行数据验证。

例如,在一个表单验证函数中:

function validateForm(formData) {
  // Other validations...

  if (formData.startDate && !isISOString(formData.startDate)) {
    return {
      valid: false,
      error: "Start date must be in ISO format"
    };
  }

  // More validations...

  return { valid: true };
}

改进后的函数现在已经足够健壮,能够处理意外输入,并为 ISO 格式的日期字符串提供可靠的验证。

总结

在这个实验中,你学习了如何验证一个字符串是否符合简化扩展的 ISO 格式(ISO 8601)。以下是你所完成的内容:

  1. 了解了 ISO 8601 日期格式及其结构。
  2. 明白了 JavaScript 的 Date 对象如何处理 ISO 格式的字符串。
  3. 创建了一个函数来验证字符串是否完全符合 ISO 格式。
  4. 用各种日期格式测试了该函数。
  5. 改进了函数以处理边界情况,使其更加健壮。

这项技能在处理 API、数据库或任何需要统一日期格式的系统时特别有用。ISO 8601 格式被广泛使用,因为它避免了歧义,并提供了一种标准化的方式来表示日期和时间。

本次实验的关键要点如下:

  • ISO 8601 格式遵循特定的模式:YYYY-MM-DDTHH:mm:ss.sssZ
  • JavaScript 的 Date.prototype.toISOString() 方法始终以这种格式输出日期。
  • 验证日期需要同时检查有效性和格式。
  • 正确的错误处理能使验证函数更加健壮。

现在,你可以运用这些知识来构建更可靠的应用程序,以正确处理日期和时间数据。