Niels Basjes
Niels Basjes

Reputation: 10652

Create company specific timezone for 'working day' in java

I work at a company where part of the work for a day is done in the early hours of the next day (i.e. shipping orders). Now for several processes (mainly reporting), we want to let the 'working day' end at 04:00 the next morning so we get more consistent reporting values per day.

We want this to always be at 04:00 the next morning and since we are affected by daylight saving times in our area (Europe - Netherlands) we effectively want a 4 hour shifted variant of our normal timezone 'Europe/Amsterdam' (in our case).

To make this as easy to use for all applications in our company I would like to create a small library that simply contains the code to provide my coworkers to get a modified instance of TimeZone that does this. That way all normal time/date manipulation methods can be used in conjunction with this special time zone.

I did a deep dive into the standard Java 8 code/Javadoc related to the TimeZone/ZoneInfo instances and at this moment I do not understand what the correct field is to change in the returned TimeZone/ZoneInfo instance.

At this point, my best guess is setting the RawOffset to 4 hours, but I'm not sure.

What is the correct way to achieve my goal?


Update:

I had a look at the suggested LocalTime and as I expected: It needs a timezone definition as being what it should use as "Local" when converting an existing timestamp (usually epoch milliseconds) into the "Local" timezone.

Looking at all these classes seems like I'll be using the LocalDate more often than the LocalTime.

Effectively the code I expect to have is something like this:

long epoch =  1525033875230L; // Obtained from some dataset
LocalDate localDate = LocalDateTime
  .ofInstant(Instant.ofEpochMilli(epoch), 
             ZoneId.of("Europe/Amsterdam"))
  .toLocalDate();

Where I expect that I need to change that Zone into the 'right one'.

Upvotes: 0

Views: 1620

Answers (1)

Anonymous
Anonymous

Reputation: 86359

If I have got that correctly, what you really need is a way to convert a milliseconds value since the epoch to a date in a way where days don’t change a 00:00 but not until 04:00.

static ZoneId zone = ZoneId.of("Europe/Amsterdam");
static LocalTime lastShiftEnds = LocalTime.of(4, 0);

public static LocalDate epochMilliToDate(long epoch) {
    ZonedDateTime dateTime = Instant.ofEpochMilli(epoch)
            .atZone(zone);
    if (dateTime.toLocalTime().isAfter(lastShiftEnds)) { // normal date-time
        return dateTime.toLocalDate();
    } else { // belonging to previous day’s night shift
        return dateTime.toLocalDate().minusDays(1);
    }
}

Use for example like this:

    long epoch = 1_525_050_875_230L;
    System.out.println(Instant.ofEpochMilli(epoch));
    LocalDate date = epochMilliToDate(epoch);
    System.out.println(date);

Output is:

2018-04-30T01:14:35.230Z
2018-04-29

From printing the Instant you can see that the time is after midnight (really 03:14:35.230 in Amsterdam time zone). And the method has correctly deemed that this time belongs to April 29 rather than April 30.

Perhaps I am missing something? On the other hand, if that were me I’d go quite a long way to avoid inventing a time zone that doesn’t exist in real life. Such a time zone would be bound to confuse your coworkers.

Upvotes: 2

Related Questions