当前位置: 首页 > 知识库问答 >
问题:

MySQL - 将 ISO-8601 持续时间转换为DATE_ADD间隔

籍星汉
2023-03-14

我在数据库中存储了两个字段,其中一个包含日期时间,另一个包含表示ISO-8601格式的持续时间的字符串(例如“P1MT2H”)。我希望能够将持续时间添加到SQL中的datetime列,似乎我应该能够使用< code>DATE_ADD来完成此操作,但我不知道是否有一种好的方法来将其转换为间隔。如果可能的话,我宁愿不用定义自己的sql函数来解析时间间隔。

共有1个答案

澹台胜
2023-03-14

我仍然很想听到这个问题的一些好答案,但目前,我已经创建了一个函数来实现这一点。我添加了第三个可选参数以在特定时区运行计算。这不是一个普遍的解决方案,但我希望它能让其他人走上正确的道路。

CREATE FUNCTION ADD_ISO_DURATION(StartDate DATETIME, Duration VARCHAR(45), Timezone VARCHAR(45))
RETURNS DATETIME
BEGIN
  DECLARE TimeStr VARCHAR(45) DEFAULT '';
  DECLARE Pos INTEGER;

  IF StartDate IS NULL OR Duration IS NULL OR LENGTH(Duration) = 0 THEN
    RETURN StartDate;
  END IF;

  IF Timezone IS NOT NULL THEN SET StartDate = CONVERT_TZ(StartDate, 'UTC', Timezone); END IF;

  IF Duration REGEXP '^P[0-9]+W$' THEN
    SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(Duration, 2, LENGTH(Duration) - 2) WEEK);
    RETURN IF(Timezone IS NULL, StartDate, CONVERT_TZ(StartDate, Timezone, 'UTC'));
  END IF;

  IF Duration NOT REGEXP '^P([0-9]+Y)?([0-9]+M)?([0-9]+D)?(T([0-9]+H)?([0-9]+M)?([0-9]+S)?)?$' THEN
    RETURN NULL;
  END IF;

  SET Pos = LOCATE('T', Duration);
  IF Pos <> 0 THEN
    SET TimeStr = SUBSTR(Duration, Pos + 1);
    SET Duration = SUBSTR(Duration, 2, Pos);
  ELSE
    SET Duration = SUBSTR(Duration, 2);
  END IF ;

  SET Pos = LOCATE('Y', Duration);
  IF Pos <> 0 THEN
    SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(Duration, 1, Pos - 1) YEAR);
    SET Duration = SUBSTR(Duration, Pos + 1);
  END IF;

  SET Pos = LOCATE('M', Duration);
  IF Pos <> 0 THEN
    SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(Duration, 1, Pos - 1) MONTH);
    SET Duration = SUBSTR(Duration, Pos + 1);
  END IF;

  SET Pos = LOCATE('D', Duration);
  IF Pos <> 0 THEN
    SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(Duration, 1, Pos - 1) DAY);
  END IF;

  IF LENGTH(TimeStr) <> 0 THEN
    SET Pos = LOCATE('H', TimeStr);
    IF Pos <> 0 THEN
      SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(TimeStr, 1, Pos - 1) HOUR);
      SET TimeStr = SUBSTR(TimeStr, Pos + 1);
    END IF;

    SET Pos = LOCATE('M', TimeStr);
    IF Pos <> 0 THEN
      SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(TimeStr, 1, Pos - 1) MINUTE);
      SET TimeStr = SUBSTR(TimeStr, Pos + 1);
    END IF;

    SET Pos = LOCATE('S', TimeStr);
    IF Pos <> 0 THEN
      SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(TimeStr, 1, Pos - 1) SECOND);
      SET TimeStr = SUBSTR(TimeStr, Pos + 1);
    END IF;
  END IF ;

  RETURN IF(Timezone IS NULL, StartDate, CONVERT_TZ(StartDate, Timezone, 'UTC'));
END $$
 类似资料:
  • 我正在寻找一种从“ISO 8601持续时间格式”(P0DT0H0M0S)转换为小时的便捷方法。 到目前为止,我想到了这个: 如您所见,我的方法是将数字拆分并乘以24、1、1/60、1/3600以得到小时。我可以减少代码量吗? 样本数据和所需结果 输入: 'P1DT2H3M44S' (1 天 2 小时 3 分 44 秒) 期望输出: 26.062222222222222 (这是小时)

  • 在ISO 8601中,持续时间的格式为<code>P[n]Y[n]M[n]DT[n]H[n]M[n]S。 例子: 20秒: 一年两个月三天四小时五分钟六秒: 问题: 给定一个包含iso 8601格式的持续时间的字符串。我想获得这段时间的总秒数。标准C 11中推荐的实现方式是什么? 备注: 例如,boost DateTime中有ptime from _ iso _ string(STD::strin

  • 我如何转换 00:00:46.70 到 T0M46S 我尝试 但它给了我这样的东西: PT0H00M 注意我想要持续时间...不是日期!

  • 有很多问题询问如何以另一种方式执行此操作(从这种格式转换),但我找不到有关如何在PHP中以ISO 8601持续时间格式输出的任何内容。 所以我有一堆可读格式的持续时间字符串——我想动态地将它们转换成ISO 8601格式,以打印HTML5微数据的持续时间。下面是一些输入字符串的示例,以及它们应该如何格式化 我可以在PHP中将字符串推入间隔对象: 但似乎没有ISO 8601输出选项 我应该如何处理这个

  • 问题内容: 我正在尝试以 2015-08-20T08:26:21.000Z* 到 2015-08-20T08:26:21Z 的格式创建字符串 * 我知道可以使用某些String拆分技术来做到这一点,但是我想知道是否有一种优雅的解决方案(只需最少的代码更改)。 以上都是时间字符串,我需要的最后一个是ISO 8601中的Date。http://tools.ietf.org/html/rfc3339#s

  • 在ISO 8601中,持续时间的格式为PT5M(5分钟)或PT2H5M(2小时5分钟)。我有一个JSON文件,其中包含这种格式的值。我想知道spark是否可以提取分钟的持续时间。我尝试将其读取为“DateType”,并使用“minutes”函数获取分钟数,结果返回空值。 示例json 目前,我正在将其作为字符串读取并使用“regex_extract”函数。我想知道一种更有效的方法。 https:/