0

I am trying to do a data generator using Gatling and a scala pluging(https://github.com/jeanadrien/gatling-mqtt-protocol). The data generated include a date.

Here is the relevant code :

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)
 }

My problem is that around 90% of the date generated are at this format :

2020-09-02T17:06:48Z

While around 10% of the date generated are at this format :

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

I only want the first format. I tried to add

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

when I saw the problem for the first time but it has no effect.

bloub
  • 510
  • 1
  • 4
  • 21
  • I recommend you don’t use `SimpleDateFormat` and `Calendar`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use `OffsetDateTime` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Sep 03 '20 at 03:15
  • Hardcoding `Z` as a literal in the format pattern string is wrong. Never do that. `Z` is an offset (of zero) from UTC and must be formatted as an offset, or you will very likely get incorrect results. See for example [parsing date/time to localtimezone](https://stackoverflow.com/questions/51206465/parsing-date-time-to-localtimezone). – Ole V.V. Sep 03 '20 at 03:18

2 Answers2

2

If you have to use the Calender API then you can follow the answer by @Arvind but I suggest that you move to newer date time API.

Setting timezone on formatter is useful only for temporals which lack timezone information. For timezone aware temporals you will need to convert them to required timezone.

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)
 }
sarveshseri
  • 13,738
  • 28
  • 47
1

I tried to add

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

when I saw the problem for the first time but it has no effect.

No matter what time-zone you add, the result will always end with Z; nothing other than that (i.e. never Z02:00 as you have mentioned) until you add something else after that explicitly. The reason is that you are adding Z as a literal ('Z') and therefore it will always be printed as Z and nothing else.

Had your pattern been as follows:

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

the result would have been different for different timezone because in this pattern, Z specifies Zone-Offset and not the literal, Z (i.e. 'Z') e.g.

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()));
    }
}

Output:

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

I recommend you switch from the outdated and error-prone java.util date-time API and SimpleDateFormat to the modern java.time date-time API and the corresponding formatting API (package, java.time.format). Learn more about the modern date-time API from Trail: Date Time.

Using modern date-time 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")));
    }
}

Output:

2020-09-02T21:30:36.770160Z
2020-09-02T21:30:36Z
2020-09-02T21:30:36+0000
2020-09-02T21:30:36UTC
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • "No matter what time-zone you add, the result will always end with Z; nothing other than that (i.e. never 02:00 as you have mentioned) until you add something else after that explicitly". You were right. the timestamp used to fill a file and I figured out that some entries add this +02:00. When generating just the date the original code was working ! Sorry and thx – bloub Sep 03 '20 at 14:31