简体   繁体   中英

How can I set an Instant to a specific time?

I've been trying to set an instant to a specific time, following stackoverflow advice, but I'm having trouble doing so. I tried the following:

Instant instant = Instant.atZone(ZoneOffset.UTC)
                        .withHour(StdIn.readInt())
                        .withMinute(StdIn.readInt())
                        .withSecond(0)
                        .toInstant();

However I get the error:

error: non-static method atZone(ZoneId) cannot be referenced from a static context

Btw the StdIn.readInt() is just a library that reads numbers from input.

Let's say I want to set an Instant to 5:10am. How do I do that?

Let's say I want to set an Instant to 5:10am. How do I do that?

I doubt you want to do that. It's not possible in the basic sense, so, the formula would be:

  • Have an instant, derived however you please.
  • Given that instants are about a moment in time, and human concepts like minutes and days do not apply to this, you can't set an instant's 'minute' to anything. Therefore, Instants are not useful for this, and you must move away from it. Convert to some notion that DOES know what a minute is... convert it to a ZonedDateTime.
  • Take the ZDT and set whatever specifics you want.
  • Convert the ZDT back to an instant.

This is a long song and dance routine and it suggests that you may not actually 'want' what you want. Perhaps whatever code you wrote that currently uses Instant could be rewritten to use something more appropriate, such as ZonedDateTime or perhaps LocalDateTime .

But, if you must:

Instant original = Instant.now();
ZonedDateTime zdt = original.atZone(Zone.UTC);
// setting minutes and seconds _AT UTC_? That sounds.. bizarre.
// what in the blazes is your use case??

ZonedDateTime adjusted = zdt
  .withHour(hour).withMinute(minute).withSecond(0)
  .withNano(0) // you forgot about the nanos!
  ;

Instant out = adjusted.toInstant();

To grok the difference between ZDTs and Instants:

Imagine you make an appointment with your barber. That appointment is best stored as a ZDT: Your appointment is on January 9th, 2023, quarter past 9 in the morning, and as the barber is in Amsterdam, at zone Europe/Amsterdam.

The time between right this very moment and your appointment is what it is.. when you fly to another time zone it will not change. In that sense it seems like an instant. But it is not: If The Netherlands decrees that henceforth The Netherlands will stick to summertime forever and will no longer observe daylight savings time, the very moment that the law is ratified, your appointment will immediately be one hour closer to right now than it was the instant before it was ratified*.

ZonedDateTimes do that; they adjust along (you'll have to wait for a new timezone definition to be downloaded, but they'll pick this up and correctly report on the time remaining until your barber appointment, automatically).

Instants don't. They don't even have a timezone. They never change like that. Think more cosmic.

That's the difference.

*) But, rzwitserloot, That is preposterous, That would never happen, Ah, but, you see, it probably would .

tl;dr

You asked:

set an Instant to 5:10am

OffsetDateTime                      // Represent a moment, a specific point on the timeline, as seen through a number of hours-minutes-seconds ahead or behind the baseline of UTC.
.now( ZoneOffset.UTC )              // Capture the current moment as seen at UTC, that is, with an offset of zero hours-minutes-seconds from UTC. Returns a `OffsetDateTime` object.
.with( LocalTime.of( 5 , 10 ) )     // Adjust from current time-of-day to this specific time-of-day. Keep the date the same, keep the offset the same. Returns a new second `OffsetDateTime` object, per immutable objects pattern.
.toInstant()                        // Extract an `Instant` object, representing a moment as seen strictly in UTC, always with an offset of zero.
.toString()                         // Generate text representing the value of this `Instant` object, in standard ISO 8601 format.

2021-02-16T05:10:00Z

Details

Let's say I want to set an Instant to 5:10am.

It sounds like you want to start with the current date as seen in UTC (an offset of zero hours-minutes-seconds), and assign a certain time-of-day.

  • Represent time-of-day with LocalTime .
  • Use OffsetDateTime first, then extract Instant .

The Instant class is the basic building-block class of java.time . It represents a moment, a specific point on the timeline, as seen in UTC (that is, with an offset of zero hours-minutes-seconds from UTC). This class by itself has a limited feature set, as it is intended to be used by more complicated classes such as OffsetDateTime & ZonedDateTime .

The OffsetDateTime class, in contrast to Instant , is more flexible, with more features. One of those features is the with method. You can pass a LocalTime object to adjust to that specific time-of-day.

Notice that java.time use immutable objects . So with method generates a new fresh OffsetDateTime object with values based on the original. The original is unchanged.

LocalTime localTime = LocalTime.of( 5 , 10 ) ;               // 5:10 AM, in 24-hour clock.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;  // Current moment as seen in UTC, an offset of zero hours-minutes-seconds.
OffsetDateTime odtAt0510 = odt.with( localTime ) ;
Instant instant = odt.toInstant() ;

See this code run live at IdeOne.com .

instant.toString(): 2021-02-16T05:10:00Z

Regarding your code:

                        .withHour(StdIn.readInt())
                        .withMinute(StdIn.readInt())

Generally it is better to first gather your inputs from user, then perform your business logic. Segregating your code will make it easier to read, test, and debug.

…
int hour = StdIn.readInt() ;
int minute = StdIn.readInt() ;
…
LocalTime localTime = LocalTime.of( hour , minute ) ;
…

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM