【问题标题】:Gatling Scala date randomly not well formatedGatling Scala 日期随机格式不正确
【发布时间】:2020-09-02 17:27:10
【问题描述】:

我正在尝试使用 Gatling 和 scala 插件 (https://github.com/jeanadrien/gatling-mqtt-protocol) 做一个数据生成器。生成的数据包括日期。

这里是相关代码:

val format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
format.setTimeZone(TimeZone.getTimeZone("UTC"));

  val publish = repeat(repeatTimes) {
   feed(feeder)
    .exec(mqtt("publish")
    .publish(format.format(Calendar.getInstance().getTime( )), QoS.AT_LEAST_ONCE, retain = false))
    .pause(pauseTime)
 }

我的问题是大约 90% 的生成日期都是这种格式:

2020-09-02T17:06:48Z

虽然大约 10% 的生成日期采用这种格式:

2020-09-02T17:06:48Z02:00

我只想要第一种格式。我尝试添加

format.setTimeZone(TimeZone.getTimeZone("UTC"));

当我第一次看到问题但没有效果时。

【问题讨论】:

  • 我建议你不要使用SimpleDateFormatCalendar。这些类设计不良且过时,尤其是前者,尤其是出了名的麻烦。而是使用来自java.time, the modern Java date and time APIOffsetDateTimeDateTimeFormatter
  • Z 硬编码为格式模式字符串中的文字是错误的。永远不要那样做。 Z 是与 UTC 的偏移量(零),必须格式化为偏移量,否则您很可能会得到不正确的结果。参见例如parsing date/time to localtimezone

标签: scala date simpledateformat gatling


【解决方案1】:

如果您必须使用 Calender API,那么您可以按照 @Arvind 的答案进行操作,但我建议您使用更新的日期时间 API。

在格式化程序上设置时区仅对缺少时区信息的时间有用。对于时区感知时间,您需要将它们转换为所需的时区。

val dateTimeFormat = DateTimeFormatter.ISO_DATE_TIME

  val publish = repeat(repeatTimes) {
   feed(feeder)
    .exec(
      mqtt("publish")
        .publish(
          ZonedDateTime.now().withZoneSameInstant(ZoneId.of("UTC")), 
          QoS.AT_LEAST_ONCE,
          retain = false
        )
    )
    .pause(pauseTime)
 }

【讨论】:

  • 或者只是OffsetDateTime.now(ZoneOffset.UTC))。我通常更喜欢单参数 now 方法而不是无参数变体。
  • 是的。我想考虑日期时间来自其他地方的可能性。
【解决方案2】:

我尝试添加

format.setTimeZone(TimeZone.getTimeZone("UTC"));

当我第一次看到问题但没有效果时。

无论你添加什么时区,结果总是以Z结尾;除此之外没有什么(即永远不会像您提到的那样Z02:00),直到您明确添加其他内容。原因是您将 Z 添加为文字 ('Z'),因此它将始终打印为 Z,仅此而已。

你的模式是否如下:

yyyy-MM-dd'T'HH:mm:ssZ

不同时区的结果会有所不同,因为在此模式中,Z 指定了 Zone-Offset 而不是文字,Z(即'Z')例如

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
        
        format.setTimeZone(TimeZone.getTimeZone("UTC"));
        System.out.println(format.format(Calendar.getInstance().getTime()));
        
        format.setTimeZone(TimeZone.getTimeZone("Europe/London"));
        System.out.println(format.format(Calendar.getInstance().getTime()));
        
        format.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
        System.out.println(format.format(Calendar.getInstance().getTime()));
    }
}

输出:

2020-09-02T21:15:36+0000
2020-09-02T22:15:36+0100
2020-09-03T02:45:36+0530

我建议您从过时且容易出错的 java.util 日期时间 API 和 SimpleDateFormat 切换到 modern java.time 日期时间 API 和相应的格式化 API(包,java.time.format)。从 Trail: Date Time 了解有关现代日期时间 API 的更多信息。

使用现代日期时间 API:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Instant instant = Instant.now();

        // Printing default pattern (i.e. whatever Instant#toString returns)
        System.out.println(instant);

        // Get ZonedDateTime from Instant
        ZonedDateTime zdt = instant.atZone(ZoneId.of("Etc/UTC"));

        // Print custom formats
        System.out.println(zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX")));
        System.out.println(zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ")));
        System.out.println(zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssz")));
    }
}

输出:

2020-09-02T21:30:36.770160Z
2020-09-02T21:30:36Z
2020-09-02T21:30:36+0000
2020-09-02T21:30:36UTC

【讨论】:

  • “无论您添加什么时区,结果都将始终以 Z 结尾;除此之外没有其他内容(即永远不会像您提到的那样 02:00),直到您在此之后明确添加其他内容” .你是对的。用于填充文件的时间戳,我发现一些条目添加了这个 +02:00。当只生成原始代码工作的日期时!抱歉,谢谢
猜你喜欢
  • 2020-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-20
  • 2012-10-14
相关资源
最近更新 更多