1

I have a spring boot backend and I want to publish news at 9am UTC+1 everyday.

I would like to get a java.time.Instant for:

  • today 9am UTC+1
  • tomorrow 9am UTC+1

Depending on if we 9am, how can I do it reliably for all my clients?

Dimitri Kopriwa
  • 13,139
  • 27
  • 98
  • 204
  • Could you tell us if *depending on if we 9am* is related to UTC+1 or to any arbitrary time zone or offset? I mean do you want to check for 9AM UTC+1 only? – deHaar Mar 17 '20 at 14:23

2 Answers2

2

You can use OffsetDateTime like this:

LocalTime targetTime = LocalTime.of(9, 0);

OffsetDateTime dateTime = OffsetDateTime.now(ZoneOffset.ofHours(1));
if (dateTime.toLocalTime().compareTo(targetTime) >= 0)
    dateTime = dateTime.plusDays(1);
Instant instant = dateTime.with(targetTime).toInstant();

System.out.println(instant);

Output (executed at 2020-03-17T14:47+01:00)

2020-03-18T08:00:00Z

Change the >= to > if exactly 9 AM should stay as today.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Good answer. I’d find `dateTime.toLocalTime().isAfter(targetTime)` clearer to read. – Ole V.V. Mar 17 '20 at 17:25
  • @OleV.V. `isAfter()` means `>`, and I'm doing `>=`, which would be `! before()`, except the `!` and the `before()` would be separated by more code, making it less clear. At least to me. – Andreas Mar 17 '20 at 18:48
0

After clarifying some misunderstandings, the answer was adjusted to use the default time zone of the client and return an Instant.

That means, you can use a ZonedDateTime with the system zone for this, have a look at the following method and its comments:

public static Instant determineNextNewsRelease() {
    // get the current time using the default time zone of the client
    ZonedDateTime now = ZonedDateTime.now(ZoneId.systemDefault());
    // get 9 AM using the same day/date
    ZonedDateTime nineAM = now.with(LocalTime.of(9, 0));

    // and check if now is before nineAM
    if (now.isBefore(nineAM)) {
        return nineAM.toInstant();
    } else {
        return nineAM.plusDays(1).toInstant();
    }
}

Use the method like this:

public static void main(String[] args) {
    Instant nextNewsRelease = determineNextNewsRelease();
    // and print the result
    System.out.println("Next news will be released at "
            + nextNewsRelease.toEpochMilli() + " (" 
            + ZonedDateTime.ofInstant(nextNewsRelease, ZoneId.systemDefault())
            + ")");
}

The result printed is

Next news will be released at 1584518400000 (2020-03-18T09:00+01:00[Europe/Berlin])

Try it...

deHaar
  • 17,687
  • 10
  • 38
  • 51
  • That doesn't answer the part of the question saying *"Depending on if we 9am"*, i.e. you're not showing how to check for that. – Andreas Mar 17 '20 at 13:49
  • That doesn't exactly honor the part of the question saying *"I would like to get a `java.time.Instant`"*, i.e. the result of the answer is not an **`Instant`**. – Andreas Mar 17 '20 at 13:51
  • If you can read `1584518400000` as `2020-03-18T08:00:00Z` without a computer, then you're a heck of a lot smarter than I am. – Andreas Mar 17 '20 at 13:54
  • When I run this code, I get `2020-03-17T14:00+01:00 ——> 1584450000000` since I'm in time zone `America/New_York`. Sorry, gonna have to down-vote *(for now)* for returning the wrong result (2 PM is not 9 AM). – Andreas Mar 17 '20 at 13:59
  • I get `1584536400000 (2020-03-18T14:00+01:00)`. --- *FYI:* I'll be able to remove down-vote after an edit, so I could likely do it now, but answer is still wrong. --- *Hint:* Specify the time zone offset on the `now()` call, and remove the `withOffsetSameInstant()` call, so the 9 AM will be *in* that zone. Like [I'm doing](https://stackoverflow.com/a/60723716/5221149). Of use `withOffsetSameLocal()`, but doing it on the `now()` call is better. – Andreas Mar 17 '20 at 14:16
  • The chat hasn't clarified anything. Ok, it clarified something, but then added more confusion. --- As for your answer, the newpaper that is supposed to be released at 9:00 AM in some(?) time zone, will be released next at `4:16:23.958 PM`? Really?!? Isn't that a bit late in the day? 6+ hours late? Didn't you look at your own output when you copy/pasted it into the answer? Did "news will be release at 958 ms past the second" look right to you? – Andreas Mar 17 '20 at 18:54
  • @Andreas of course, it doesn't ;-) I just mixed up the `ZonedDateTime`s... and printed the `now` instead of the next release... – deHaar Mar 18 '20 at 07:51
  • Much better. One small piece of improvement: When you call `withXxx()`, it creates a new `LocalTime`, a new `LocalDateTime`, and a new `ZonedDateTime`. Since you call a `withXxx()` 4 times, that means 12 new objects created. If you instead call `now.with(LocalTime.of(9, 0))`, then only 1 of each would be created, not 4 of each. – Andreas Mar 18 '20 at 16:36
  • @Andreas that's indeed a big *small piece of improvement*. I didn't know, thanks. – deHaar Mar 19 '20 at 07:22