2

When using SimpleDateFormatter.format in the following code, hours between 12:00 and 12:59 are shown as 00:00 to 00:59 in startDateText TextView, while since 13:00 on they are correctly shown as 13:xx, 14:xx up to 23:59.

---- Refactored code as requested When the string in the dtold.parse(...) is an the in example the output hour is 00:00, when it is "13:00" it is correctly "13:00"

import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;


// one class needs to have a main() method
public class HelloWorld
{
  // arguments are passed using the text field below this editor
  public static void main(String[] args)
  {
        SimpleDateFormat dtnew = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
        SimpleDateFormat dtold = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

            try {

            Calendar cal = Calendar.getInstance();
            cal.setTime(dtold.parse("2017-03-12 12:33:33"));
            cal.add(Calendar.SECOND, 10);
            System.out.println(dtnew.format(cal.getTime()));

        } catch (Exception e) {

            throw new RuntimeException(e);
        }


  }
}
sthor69
  • 638
  • 1
  • 10
  • 25
  • is it intentional that your dtnew has HH that means (00 - 23), and dtold hh (00-11 AM/PM) – Bogdan Lukiyanchuk Apr 07 '18 at 14:58
  • Yes. I'm modifying the text adding the part covering date creation. I don't remember why I used this construct, but it worked except from the issue of 12:xx – sthor69 Apr 07 '18 at 15:03
  • 3
    Could you please reduce your code to a [MCVE](https://stackoverflow.com/help/mcve)? eg *don't* use just use `ZonedDateTime.now()` (which could be AM or PM) but rather build a specific time that produces a specific (presumably incorrect) output and show what output you expect. Also, use `System.out.println()` instead so folks can reproduce your problem without having a `TextView` – Bohemian Apr 07 '18 at 15:12
  • 1
    @sthor69 I think the information is lost when you do dtold.parse(date). The fact that your code works with time 13:00 - 23:59 just undocumented feature (or bug) – Bogdan Lukiyanchuk Apr 07 '18 at 15:14
  • @Bohemian I typically use exactely the same code that is not working, as modifying it I could add unintentional modifications that makes the issues to disappear. In this case I actually solve my problem (I get working code) but I may not understand what's the problem with THIS code – sthor69 Apr 07 '18 at 15:22
  • @sthor69 change `zdt = ZonedDateTime.now(z)` to assign an exact reproducable value that demonstrates the problem and change `startDateText.setText(...)` to `System.out.println(...)`. That is not asking for too much, and btw this site is not a debugging service. Minimize, or at least make your example code portable, so it is useful to *others* (not just you). – Bohemian Apr 07 '18 at 16:07
  • Since you can use the modern Java date and time classes — `ZoneId` and `ZonedDateTime` — don’t also use the old-fashioned ones — `SimpleDateFormat`, `Date` and `Calendar`. The new ones offer all the functionality you need, and mixing old and new is overcomplicating things and asking for trouble. – Ole V.V. Apr 07 '18 at 18:13
  • Are you on Android? I believe there are some differences between the standard `SimpleDateFormat` behaviour and the Android variant. See for example [Is SimpleDateFormat in Java and Android different?](https://stackoverflow.com/questions/49673279/is-simpledateformat-in-java-and-android-different) – Ole V.V. Apr 07 '18 at 18:18
  • And if you are, are you using `java.text.SimpleDateFormat` or `android.icu.text.SimpleDateFormat`? – Ole V.V. Apr 07 '18 at 18:24
  • `zdt.plusSeconds(10).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))`. – Ole V.V. Apr 07 '18 at 19:28
  • 1
    @Ole V.V. no, I'm not using Android. It's a pure java application – sthor69 Apr 07 '18 at 20:05
  • 1
    @Bohemian refactored code as requested – sthor69 Apr 07 '18 at 20:20
  • I have reproduced on Java 1.8.0_131. I got `12-03-2017 00:33:43`. Voting to reopen question. – Ole V.V. Apr 07 '18 at 20:48
  • What fooled me (and you??) was that you declared `dtnew` before `dtold`, but then used them in the opposite order. The behaviour is as expected. When parsing using `dtold`, which has lowercase `hh`, hours from 01 through 12 are expected and interpreted with either AM or PM. With no AM or PM marker, AM is used as default. And 12 AM means the same as 00 on a 24 hour clock, so this is what you get when you format using uppercase `HH`. – Ole V.V. Apr 07 '18 at 20:58
  • 1
    @ Ole V.V. Thank you very much. I don't remember why I used the different format (HH and hh), but this was the issue @ Bohemian you're right. I used StackOverflow as a debugger system, due to the hurry I was in trying to solve the issue. I'll pay more attention in not doing that in the future – sthor69 Apr 09 '18 at 10:09

1 Answers1

3

First a couple of formatters like yours, only using DateTimeFormatter from java.time, the modern Java date and time API:

private static DateTimeFormatter dtfOld = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static DateTimeFormatter dtfNew = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");

Two things to note: (1) Declare the formatters in the logical order, the order in which you are going to use them. Using the opposite order in the question confused me, and I’m unsure whether it confused yourself too. (2) In dtfOld use uppercase HH for hour of day in the interval 00 through 23. Lowercase hh is for hour within AM or PM from 01 through 12 (in this case the same format pattern letters apply for SimpleDateFormat and DateTimeFormatter; there are differences, though). Now the rest is pretty boring, only simpler than your code:

    LocalDateTime parsed = LocalDateTime.parse("2017-03-12 12:33:33", dtfOld);
    System.out.println(parsed);
    LocalDateTime dateTime = parsed.plusSeconds(10);
    System.out.println(dateTime);
    System.out.println(dateTime.format(dtfNew));

Output is:

2017-03-12T12:33:33
2017-03-12T12:33:43
12-03-2017 12:33:43

I am recommending java.time. The old date and time classes that you used — SimpleDateFormat, Calendar and Date — are long outdated. It’s not only in this case that the modern classes allow for simpler code, it’s quite common. I find java.time generally so much nicer to work with.

What went wrong in your code?

I gave a hint already: Lowercase hh is for hour within AM or PM from 01 through 12. When you don’t supply and parse an AM/PM marker, AM is used as the default. And 12:33:33 AM means a little more than half an hour past midnight, and is rendered as 00:33:33 on a 24 hour clock.

The times from 13:00 up to 23:59? They don’t exist in AM. Apparently SimpleDateFormat doesn’t care and just extrapolates from the hours from 01 through 11 and therefore happens to give you the time you had expected. There’s a trick to tell it not to; but I wouldn’t want to bother, I’d rather not use the class at all.

Link

Oracle tutorial: Date Time explaining how to use java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161