【问题标题】:How to convert local date to UTC in Mirth?如何在 Mirth 中将本地日期转换为 UTC?
【发布时间】:2018-06-12 15:58:15
【问题描述】:

在 Mirth 中,我收到一个本地日期时间字符串 (201801011000),我需要将其转换为 UTC。我很快发现使用经典的 js new Date() 效果不好。

例如:

var d = new Date("2018-01-01 10:00");
logger.info(d.toString());

给我一​​个Invalid Date

所以经过更多搜索后,我发现我可以做到这一点:

var d = DateUtil.getDate("yyyyMMddHHmm", "201801011000");

从这里我被困住了。我不知道如何将其转换为 UTC。假设本地服务器时区现在就足够了,但将来我还需要设置一个特定的非本地时区。

我试图获得可以与Object.getOwnPropertyNames(d) 一起使用的方法,但这给了我有用的TypeError: Expected argument of type object, but instead had type object

我还尝试查找 DateUtil 的 java 文档并尝试了一些方法,但没有任何效果。

有人知道如何将日期字符串从本地时间转换为 UTC 吗?欢迎所有提示!

【问题讨论】:

  • 根据these docs,看起来这是Java,它返回一个java.util.Date 对象?如果是这样,这个问题已经回答了很多次了。我有点困惑,因为我不认识 Mirth 而你提到了“经典 js”——这是 Java 还是 JavaScript?
  • 我无法回答这个问题,但作为背景 - 两者兼而有之。 :) Mirth 使用 Rhino JavaScript 引擎编写脚本,这意味着您编写 JS 代码并可以访问类路径中的所有 Java 类。它可以而且确实会混淆诸如“我在这里处理的是 JavaScript 还是 Java String 对象?!”之类的问题。我只能假设它与日期和时间操作类似。
  • @TarmoR 这听起来很糟糕
  • 仅供参考,非常麻烦的旧日期时间类,例如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被 Java 8 中内置的 java.time 类所取代之后。见Tutorial by Oracle
  • 您应该使用 java8 提供的最新 java 类进行转换。我已添加我的答案以供您解释。

标签: date utc date-conversion mirth mirth-connect


【解决方案1】:

好的,在搞砸了大约两天后,我终于找到了解决方案。最后我不得不使用 Java,但由于我无法导入任何 Java 依赖项,我不得不使用它们的直接类路径(例如:java.text.SimpleDateFormat)。

最后这对我有用:

var datestr = "201207011000".slice(0, 12);  // This is just a datetime string to test with

var formatter_hl7 = new java.text.SimpleDateFormat("yyyyMMddHHmm");
formatter_hl7.setTimeZone(java.util.TimeZone.getTimeZone("CET"));
var formatter_utc = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm");
formatter_utc.setTimeZone(java.util.TimeZone.getTimeZone("UTC"));

var date_in_utc = formatter_utc.format(formatter_hl7.parse(date_str));

不管怎样,祝大家有个美好的一天!

【讨论】:

  • 谁反对这个;你为什么不投票?请解释它有什么问题。
  • 可能是因为您使用了糟糕的旧日期时间类,这些类在几年前被优秀的 java.time 类所取代。
  • 只是建议:不要使用旧的java类进行转换。
【解决方案2】:

tl;博士

  • 不要使用DateUtil。 (也许是 Apache DateUtils 库?)
  • 不要使用糟糕的旧日期时间类,例如java.util.Date
  • 使用现代行业领先的 java.time 类。

解析缺少偏移量的字符串,然后为 UTC 本身分配零偏移量的代码。

LocalDateTime                // Represents a date and a time-of-day but without any concept of time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline.
.parse( 
    "201801011000" ,
     DateTimeFormatter.ofPattern( "uuuuMMddHHmm" )
)  
.atOffset( ZoneOffset.UTC )  // Assign an offset-from-UTC. Do this only if you are CERTAIN this offset was originally intended for this input but was unfortunately omitted from the text. Returns an `OffsetDateTime`.
.toInstant()                 // Extract an `Instant` from the `OffsetDateTime`. Basically the same thing. But `Instant` is always in UTC by definition, so this type is more appropriate if your intention is to work only in UTC. On the other hand, `Instant` is a basic class, and `OffsetDateTime` is more flexible such as various formatting patterns when generating `String` object to represent its value.

使用 java.time

Java 中的现代方法使用 java.time 类。这个行业领先的框架取代了非常麻烦的旧日期时间类,例如DateCalendarSimpleDateFormat

DateTimeFormatter

解析您的输入字符串。定义要匹配的格式模式。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMddHHmm" ) ;
String input = "201801011000" ;

LocalDateTime

解析为 LocalDateTime,因为您的输入缺少时区指示符或与 UTC 的偏移量。

LocalDateTime ldt = LocalDateTime.parse( input , f ) ;

缺少区域或偏移意味着这代表一个时刻,不是时间轴上的一个点。相反,这代表了大约 26-27 小时范围内的潜在时刻,即全球时区范围。

OffsetDateTime

如果您确定此日期和时间旨在表示 UTC 中的某个时刻,请应用常量 ZoneOffset.UTC 以获取 OffsetDateTime 对象。

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;

ZonedDateTime

您的问题含糊不清。听起来您可能知道用于此输入的特定时区。如果是这样,分配一个ZoneId 以获得一个ZonedDateTime 对象。

了解与 UTC 的偏移只是小时、分钟和秒数。不多也不少。相比之下,时区要多得多。时区是某个地区的人们使用的偏移量的过去、现在和未来变化的历史。

continent/region 的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

Instant

调整回 UTC 的快速方法是提取 Instant 对象。 Instant 始终采用 UTC。

Instant instan = zdt.toInstant() ;

ISO 8601

提示:不要使用自定义格式将日期时间值交换为文本,而应仅使用标准 ISO 8601 格式。标准格式实用,易于机器解析,易于跨文化的人类阅读。

java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。 ZonedDateTime::toString 方法明智地扩展了标准,将区域名称附加在方括号中。

Instant instant = Instant.parse( "2018-07-23T16:18:54Z" ) ;  // `Z` on the end means UTC, pronounced “Zulu”. 
String output = instant.toString() ;  // 2018-07-23T16:18:54Z

并且始终在字符串中包含偏移量和时区。暂时忽略偏移量/区域就像忽略价格的货币:你剩下的只是一个不值钱的模棱两可的数字。实际上,总比没有更糟糕,因为它会导致各种混乱和错误。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

  • DateUtil 属于 mirth 的 java 风格。它的名字再合适不过了:缺乏实用程序的日期实用程序类。
【解决方案3】:

在我的项目中具有将datestring本地时间转换为UTC的功能,

function getDateInUTC(dateString) {
    return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm").setTimeZone(java.util.TimeZone.getTimeZone("UTC")).format(new java.text.SimpleDateFormat("yyyyMMddHHmm").setTimeZone(java.util.TimeZone.getTimeZone("CET")).parse(dateString));
}

享受:)

【讨论】:

  • 我尝试了您的建议,但收到错误消息:TypeError: Cannot call method "format" of undefined。有什么想法吗?
  • 请导入java.text.SimpleDateFormat
【解决方案4】:

您应该使用 Java8 提供的最新类 java.time

步骤如下:

第 1 步。String 解析为 LocalDateTime

Step-2.LocalDateTime 转换为ZonedDateTime,然后我们可以在不同的timezone 之间进行转换。

希望得到帮助:

在 Mirth 中你可以写成:

String str = "201207011000"; 
var date_in_utc =java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
                .format(java.time.ZonedDateTime.of(java.time.LocalDateTime
                .parse(str,java.time.format.DateTimeFormatter
                .ofPattern("yyyyMMddHHmm")),java.time.ZoneId.of("CET"))
                .withZoneSameInstant(java.time.ZoneOffset.UTC));

完整片段:

ZoneId cet = ZoneId.of("CET");
String str = "201207011000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
LocalDateTime localtDateAndTime = LocalDateTime.parse(str, formatter);
ZonedDateTime dateAndTimeInCET = ZonedDateTime.of(localtDateAndTime, cet );
System.out.println("Current date and time in a CET timezone : " + dateAndTimeInCET);
ZonedDateTime utcDate = dateAndTimeInCET.withZoneSameInstant(ZoneOffset.UTC);
System.out.println("Current date and time in UTC : " + utcDate);
System.out.println("Current date and time in UTC : " + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").format(utcDate));

【讨论】:

    【解决方案5】:

    大声疾呼

    var d = DateUtil.getDate("yyyyMMddHHmm", "201801011000");
    var utcD = new Date(d).toISOString();
    

    编辑:关于 .toISOString() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString的信息

    【讨论】:

    • 嘿,嘘。这么晚才回复很抱歉。我尝试了你的建议,但不幸的是,第二行只得到RangeError: Date is invalid.。我登录了d,这是一个正确指向 2018 年 1 月 10 日 10 点的对象。不知道为什么不能使用Date。还有其他想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多