0

Any help or hint would be greatly appreciated. From the below code I get this date:2023-01-25 16:30:22.998. How can I get this date: "FrmDt": "2023-01-16T23:59:59.938Z". It has a "T" which I not sure what this mean?

    java.util.Date tsFrom = new java.util.Date();
    Calendar calFrom = Calendar.getInstance();
    calFrom.setTime(tsFrom);
    calFrom.add(Calendar.YEAR, -1);
    tsFrom.setTime(calFrom.getTime().getTime()); // or
    sqlTSFromDate = new Timestamp(calFrom.getTime().getTime());
    System.out.println("From date:" + sqlTSFromDate);
Albert Lam
  • 9
  • 1
  • 3
  • 1
    Take a look how that `T` is used for [ISO 8601 formats](https://en.wikipedia.org/wiki/ISO_8601). The "T" stands for "time". Here it separates the date portion from the time portion. See also questions such as [What is this date format? 2011-08-12T20:17:46.384Z](https://stackoverflow.com/q/8405087/12567365) – andrewJames Jan 25 '23 at 21:52
  • Sorry I correct the first date. It should be: "2023-01-25 16:30:22.998" vs "2023-01-16T23:59:59.938Z" – Albert Lam Jan 25 '23 at 21:56
  • 3
    So it looks like you're trying to specify a format to use when `System.out.println` prints your date. The old-fashioned way of doing this is to use a `SimpleDateFormat` object, which lets you specify exactly what format to use, and call its `format` method. However, I would recommend using the more modern classes in the `java.time` package, which means you'll use `Instant` instead of `Date` or `Calendar`, and `DateTimeFormatter` instead of `SimpleDateFormat`. – Dawood ibn Kareem Jan 25 '23 at 22:09
  • 1
    "Date" and "time" classes are simply containers, typically representing the amount of time which has passed since a given anchor point (ie the Unix Epoch), they don't tend to carry any kind of formatting concept, so you can't "change" what they print (via their `toString` implementation). Instead, you should be making use of the associated date/time formatter workflows if you want to display the date/time in some kind of desirable format – MadProgrammer Jan 25 '23 at 22:13
  • I strongly recommend you don’t use `Date`, `Calendar` and `Timestamp`. Those classes are poorly designed and long outdated. Instead use `OffsetDateTime` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). You can also pass an `OffsetDateTime` to your JDBC 4.2 driver. See for example [the good answer by Arvind Kumar Avinash here](https://stackoverflow.com/a/67505173/5772882). – Ole V.V. Jan 26 '23 at 07:29
  • Please, what were you wanting a `Timestamp` for and what made you think you needed a `T` in the middle? The two requirements are contradictory since an old-fashioned `java.sql.Timestamp` never printed that way. The `toString` method of `OffsetDateTime` gives you the `T`, but likely you need not care about the format of the `toString` method as long as you get the correct date-time value. – Ole V.V. Jan 26 '23 at 07:34
  • 1
    Also be aware that subtracting a year is a time zone dependent operation. Your `Calendar` uses the default time zone of your JVM, whereas the `Z` in your desired result tells me you want UTC time zone. Don’t you want to use the same time zone for both? – Ole V.V. Jan 26 '23 at 07:37

2 Answers2

4

tl;dr

OffsetDateTime
        .now( ZoneOffset.UTC )
        .minus( Period.ofYears( 1 ) )
        .toString()

2022-01-27T02:02:36.985475Z

ISO 8601

Study the ISO 8601 standard formats for textually representing date-time values.

Avoid legacy classes

Never use the legacy classes Date, Calendar, Timestamp. They are terribly flawed, designed by people who did not understand date-time handling.

java.time

Instead, use the java.time classes defined in JSR 310.

Apparently you want one year prior to the the current moment as seen in UTC.

Capture the current moment in UTC.

OffsetDateTime oneYearAgoInUtc = OffsetDateTime.now( ZoneOffset.UTC  );

now.toString(): 2023-01-27T02:02:36.985475Z

Go back a year, using calendar dates as seen in the offset of zero, in UTC. First define the amount of time to go back, using Period for a scale of years-months-days.

Period p = Period.ofYears( 1 );

Then subtract.

OffsetDateTime then = now.minus( p );

then.toString(): 2022-01-27T02:02:36.985475Z

See that code run at Ideone.com.

To generate text in standard ISO 8601, merely call toString. The java.time classes use ISO 8601 formats by default when generating/parsing text.

String output = then.toString() ;  // By default, standard ISO 8601 format.

2022-01-27T02:02:36.985475Z

The T separates the year-month-day portion from the hour-minute-second portion.

The Z indicates an offset from UTC of zero hours-minutes-seconds.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

As several comments said, this is an ISO 8601 date. In java, you can parse or write using SimpleDateFormat. With the Z at the end, makle sure to use UTC/Zulu time.

Amending your code:

public static String ISO_8601 = "yyyyMMdd'T'HHmmss'Z'";
...

    SimpleDateFormat dateFormat = new SimpleDateFormat(ISO_8601);
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    sqlTSFromDate = dateFormat.format(tsFrom)
pilotpin
  • 137
  • 5
  • I think there are issues in the ISO_8601, should be "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" – John Williams Jan 25 '23 at 22:52
  • 1
    **Incorrect.** Never put quotes around the `Z`. In doing so, you are instructing the parser to expect but ignore that lettter. But that letter provides vital information communicating an offset from UTC of zero-hours-minutes. Your code incorrectly discards that offset fact. – Basil Bourque Jan 26 '23 at 00:10
  • 1
    Also never use `SimpleDateFormat`. That class is notoriously troublesome and fortunately long outdated. – Ole V.V. Jan 26 '23 at 07:25