3

I am working with expiration date of card. I have a API where I will get expiration date in "yyMM" format as "String". Here I am trying to use

SimpleDateFormat with TimeZone.getTimeZone("UTC")

So my code is like

String a= "2011";
SimpleDateFormat formatter = new SimpleDateFormat("yyMM");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = formatter.parse(a);
System.out.println(date);

Now problem is, when I am passing 2011 the out it gives is Sat Oct 31 17:00:00 PDT 2020

Here you can see I am passing 11 as month but it is converting it to Oct instead of Nov.

Why?

And what other options I can use to convert string with yyMM to Date with Timezone?

user2367130
  • 125
  • 1
  • 2
  • 10
  • Why does question say `MMyy` but code says `yyMM`? The `java.util.Date` class stores a date/time as milliseconds since 1/1/1970 UTC. It doesn't have a concept of time zone, so when you call `toString()`, as implicitly done by the `print()` call, it will format the value using the **default time zone**, which apparently is `PDT` for you. If you want something else, use a `SimpleDateFormat` with explicitly specified `TimeZone`. – Andreas Oct 16 '17 at 23:26
  • 5
    You should use the Java 8 [`YearMonth`](https://docs.oracle.com/javase/8/docs/api/java/time/YearMonth.html) class. – Andreas Oct 16 '17 at 23:27
  • Your parsing is correct. It’s when you print the `Date` object, you implicitly call its `toString` method, which in turn gives you the incorrect output. It’s one case out of many for skipping the long outdated `Date` and `SimpleDateFormat` classes. Instead use the modern Java date and time API known as `java.time` or JSR-310. – Ole V.V. Oct 17 '17 at 01:36
  • Yes, your code is giving the correct `Date` - 1 November 2020, 00:00 in UTC. Now all you need to do is print it correctly, instead of converting it to PDT when you print. – Dawood ibn Kareem Oct 17 '17 at 02:09

2 Answers2

17

You should use the Java 8 YearMonth class.

String a = "2011";
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("yyMM");
YearMonth yearMonth = YearMonth.parse(a, inputFormat);

DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("MMMM yyyy");
System.out.println(yearMonth.format(outputFormat));

Output

November 2020

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Java 8 is still really new and is not yet the standard- my suggestion would be to stick to more well-supported date formats where possible. – Derek Brown Oct 16 '17 at 23:33
  • 5
    @DerekBrown Java 8 was released on March 18, 2014. In what programming world is 3.5 years ago "really new", and in what way is it "not yet the standard"? [Java 7 was end-of-life'd in April 2015](https://www.java.com/en/download/faq/java_7.xml), so Java 8 is the oldest maintained release. Java 9 has even been released by now, so you are way off the mark. – Andreas Oct 16 '17 at 23:37
  • 4
    @DerekBrown There is *no* reason to stick with the terrible old date-time classes that are now legacy, supplanted by the java.time classes years ago. Those old classes are a wretched mess that have caused no end of confusion and pain, as any quick search of Stack Overflow will show. For old versions of Java, Java 6 and Java 7, use the back-port project: [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/). – Basil Bourque Oct 16 '17 at 23:38
  • They are not even close to legacy. Take a look at the actual distribution of Java in practice: https://plumbr.eu/blog/java/java-version-and-vendor-data-analyzed-2017-edition – Derek Brown Oct 16 '17 at 23:38
  • @DerekBrown Of course there are people still on older Java. That is why the java.time folks put so much work into [*ThreeTen-Backport*](http://www.threeten.org/threetenbp/) project, for Java 6 & Java 7. – Basil Bourque Oct 16 '17 at 23:40
  • 3
    @DerekBrown The Oracle's official date/time tutorial now covers [Java 8 API](https://docs.oracle.com/javase/tutorial/datetime/TOC.html), while the old API (`Date`, `Calendar` and `SimpleDateFormat`) is in a [section called "legacy"](https://docs.oracle.com/javase/tutorial/datetime/iso/legacy.html) –  Oct 16 '17 at 23:41
  • @BasilBourque if your answer to "it is incompatible" is just to add a library- you might as well just use the tried-and-true inbuilt classes. – Derek Brown Oct 16 '17 at 23:41
  • 4
    The built-in `Date`/`Calendar` classes are tried-and-*failed*. The java.time classes are not "incompatible", they are *built into* the later versions of Java those legacy users will be moving too. Those Java 6/7 users can use the back-port for now, then later when upgrading to later Java, simply change the package names in the `import` statements. Trying to argue the case for those old date-time classes is like trying to argue for a [Yugo](https://en.wikipedia.org/wiki/Zastava_Koral) over a [Honda Civic](https://en.wikipedia.org/wiki/Honda_Civic). – Basil Bourque Oct 16 '17 at 23:45
  • @DerekBrown The old classes (`Date`, `Calendar` and `SimpleDateFormat`) have [lots of problems](https://stackoverflow.com/q/1571265/7605325) and [design issues](https://stackoverflow.com/q/1969442/7605325), mostly fixed by the new API. Now that we have a better alternative, I'd use the old classes only if I had no choice (and *"just to add a library"* is totally worth in this case, IMO) –  Oct 16 '17 at 23:46
  • 6
    @DerekBrown At what date would you recommend we start using Java 8? – Dawood ibn Kareem Oct 16 '17 at 23:52
  • 3
    @DawoodibnKareem I believe Derek Brown is one of those super conservative people who don't think things are tried-and-true until it has been replaced by at least two never versions, is at least 5 years old, and has been end-of-life'd. Of course, using tried-and-true but end-of-life'd code means you're vulnerable to security issues and your code can be hacked, but hey, hacks only happen to other people, right? You have to weigh your pros and cons, man. – Andreas Oct 17 '17 at 00:00
6

You parsed it fine, but it's printed in PDT, your local timezone.

Sat Oct 31 17:00:00 PDT 2020

Well, Date doesn't track timezones. The Calendar class does, which is internal to the formatter. But still, default print behavior is current timezone.

If you logically convert this output back to UTC, and it will be November 1 since PDT is UTC-7.

Basically, use java.time classes. See additional information here How can I get the current date and time in UTC or GMT in Java?

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • 1
    *"SimpleDateFormat don't track timezones"*? It most certainly does: [`DateFormat.setTimeZone(TimeZone zone)`](https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html#setTimeZone-java.util.TimeZone-). – Andreas Oct 16 '17 at 23:50
  • @Andreas `Calendar` class does. – OneCricketeer Oct 16 '17 at 23:51
  • Yes it does: [`Calendar.setTimeZone(TimeZone value)`](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#setTimeZone-java.util.TimeZone-) --- But your answer is about `SimpleDateFormat` and it supports time zone too, as I already mentioned. – Andreas Oct 16 '17 at 23:52
  • @Andreas Point being, the first is a redirect into the Calendar. The formatter does not store the TZ itself – OneCricketeer Oct 16 '17 at 23:54
  • From an API users point of view, that doesn't matter. As an API user, I don't really care how `SimpleDateFormat` works. I create one, tell it the time zone, and it now parses and formats using that time zone. As far as the API is concerned, it fully supports/tracks time zone. – Andreas Oct 16 '17 at 23:56