转换为 ISO8601 格式的日期时间

问题描述

我有一个 getdate() 字段,我想将其转换为 20210211T172650Z 这种格式,我该如何在 SSIS 表达式中执行此操作?

解决方法

在 SSIS 中,我们有字符串、数字和日期的数据类型。日期没有格式,当它被转换为字符串值时,你会得到本地化规则规定的任何格式。

如果你有一个你想要的特定格式,那么你需要控制它,你可以控制它的唯一方法是使用字符串数据类型。

我们将在这里使用的模式,对于每个元素,

  1. 提取数字
  2. 将数字转换为字符串
  3. 左填充/前置一个前导零
  4. 从我们的字符串中提取最后 2 个字符

当我们提取数字时,它们是数字并且数字没有前导零。我们转换为字符串,这将允许我们在它前面添加字符零,因为我们只是连接字符串。如果数字小于 10,那么在前面加一个零就会得到我们想要的结果。 9 -> 09 如果它大于 9,那么我们在那里有一个无关紧要的值。 11 -> 011。我们不在乎我们太大了,因为然后我们将取最合适的 2 个字符,使 09 -> 09 和 011 -> 11。这是制作前导零字符串的最短逻辑在 SSIS 中。

使用该逻辑,我们将为格式化字符串的每个元素创建一个变量:年、月、日、小时、分钟、秒。

什么时候开始?

我创建了一个名为 StartDate 的 DateTime 类型的变量,并将其硬编码到一个起点。这将允许我测试各种条件。如果我使用 getdate,那么我要么必须调整计算机的时钟以确保我的代码在 2001-01-01 的 01:01:01 以及 2021-12-31 的 23:59 上运行: 59.当您对代码通过所有测试感到满意时,您可以指定 StartDate 属性 EvaluateAsExpression 为 True,然后使用 GetDate()。但我不会使用 GetDate()。

GetDate 将在您每次检查时进行评估。当你的包启动时,它会显示 2021-02-12 @ 11:16 AM 但是你的包需要 5 分钟才能运行,所以当你去重用建立在 GetDate 上的值时,你现在会得到 2021-02 -12 @ 上午 11:21。

在您的情况下,如果您多次将其发送到您的 Amazon 设备,这些密钥将不匹配。相反,使用系统范围的变量,如 @[System::StartTime],它更新到包开始执行的时间,并在 SSIS 包执行期间保持不变。因此,当您对构建的表达式与业务规则相匹配感到满意时,将@[User::StartDate] 更改为使用@[System::StartTime]。它提供更新的时间,但没有时间漂移的挑战。

提取数字

SSIS 表达式语言定义了 YEARMONTHDAY,但没有时间组件的速记方法。但是,它确实具有 DATEPART 函数,您可以在其中请求任何命名的日期部分。我将在我所有的访问方法中使用它,因为它非常好且一致。

举个例子,这就是我如何获得小时。字符串文字 HOUR,我们使用我们的变量

DATEPART("HOUR",@[User::StartDate])

将数字转换为字符串

上一步给了我们一个数字,但我们要解决前导零问题,因此将其转换为字符串

(DT_WSTR,2)DATEPART("HOUR",@[User::StartDate])

转换为字符串,最大两个字符宽,我们生成的数字

左填充/前置一个前导零

字符串连接是 + 运算符,因为我们不能将字符串连接到数字,所以我们确保两边都有正确的操作数类型

"0" + (DT_WSTR,@[User::StartDate])

从我们的字符串中提取最后 2 个字符

由于此时我们可能有一个 2 或 3 个字符的字符串,我们将使用 RIGHT 函数只获取最后 N 个字符。

RIGHT("0" + (DT_WSTR,@[User::StartDate]),2)

最终连接

现在我们有了快乐的小变量并检查了边界条件,剩下的唯一事情就是创建最后一个变量,DateAsISO8601 类型的字符串,EvaulateAsExpression = True

@[User::Year] + @[User::Month] +@[User::Day] + "T" +@[User::Hour] +@[User::Minute] +@[User::Second] + "Z"