0

I have the following Timestamp:

Timestamp time = new Timestamp(1652039000000L);

This time is "2022-05-08 19:43:20.0" in local time. Are there any ways to turn this into the start of the current:

  1. Hour: "2022-05-08 19:00:00.0"
  2. Day: "2022-05-08 00:00:00.0"
  3. Week: "2022-05-02 00:00:00.0"

And then minus get the UTC time from it so that Paris (+2 hours) would return:

  1. Hour: "2022-05-08 17:00:00.0"
  2. Day: "2022-05-07 22:00:00.0"
  3. Week: "2022-05-01 22:00:00.0"
TheStranger
  • 1,387
  • 1
  • 13
  • 35
  • Is 3. supposed to denote the *second week of May in 2022*? If yes, I would think about the representation twice or more because it would look like *May 2nd, 2022*. – deHaar May 16 '22 at 10:27
  • No it is the date May 2nd, 2022. If you have May 8th, 2022 that is a sunday. From that point, the start of the week would be Monday May 2nd, 2022 00:00:00, if that makes sense. – TheStranger May 16 '22 at 10:31
  • OK, got it… It's about the start of week. – deHaar May 16 '22 at 10:36
  • These operations only make sense if you specify a timezone. I'm assuming you want UTC, right? – Sweeper May 16 '22 at 10:41
  • 2
    I strongly advise to use LocalDateTime and TemporalAdjusters to do this. `LocalDateTime ldt = time.toLocalDateTime();` – f1sh May 16 '22 at 10:42
  • @Sweeper Oh, yes I want UTC. – TheStranger May 16 '22 at 10:47
  • Subtracting two hours from a UTC time is very unlikely to ever give you the time of the same instant in Paris, just for the record… – deHaar May 16 '22 at 11:57
  • I think you want the start of the hour, day or week in Europe/Paris time zone and after that you want to convert to UTC. Have I understood correctly? I too recommend that you don’t use `Timestamp` but java.time. Also a `Timestamp` hasn’t got a time zone. – Ole V.V. May 17 '22 at 05:21

2 Answers2

5

You could use java.time for this, you'd basically have to

  • create an Instant from the milliseconds (not a Timestamp)
  • create a ZonedDateTime using a desired time zone and the Instant
  • use methods provided by java.time classes in order to truncate or adjust the time and
  • lastly, convert the Instant from one ZoneId to another one (here from "Europe/Paris" to "UTC")

Here's an example:

public static void main(String[] args) {
    // first of all, use an Instant, not a Timestamp for conversion
    Instant time = Instant.ofEpochMilli(1652039000000L);
    // define the zone for your time
    ZoneId paris = ZoneId.of("Europe/Paris");
    // then create a ZonedDateTime of it at the desired zone
    ZonedDateTime parisTime = ZonedDateTime.ofInstant(time, paris);
    // (1) truncate the time to hours
    ZonedDateTime parisTimeTilHour = parisTime.truncatedTo(ChronoUnit.HOURS);
    // (2) truncate the time to days
    ZonedDateTime parisTimeDateOnly = parisTime.truncatedTo(ChronoUnit.DAYS);
    // (3) get the first day of week and truncate that to days
    ZonedDateTime parisTimeStartOfWeek = parisTime.with(WeekFields.ISO.getFirstDayOfWeek())
                                       .truncatedTo(ChronoUnit.DAYS);
    // define a formatter to be used for output
    DateTimeFormatter isoLDT = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.S");
    // print the results:
    System.out.println("Paris: " + parisTime.format(isoLDT));
    System.out.println(" --> " + parisTimeTilHour.format(isoLDT));
    System.out.println(" --> " + parisTimeDateOnly.format(isoLDT));
    System.out.println(" --> " + parisTimeStartOfWeek.format(isoLDT));
    
    // Shift the zone to UTC, create UTC as ZoneId first…
    ZoneId utc = ZoneId.of("UTC");
    ZonedDateTime utcTime = parisTime.withZoneSameInstant(utc);
    ZonedDateTime utcTimeTilHour = parisTime.withZoneSameInstant(utc);
    ZonedDateTime utcDateOnly = parisTimeDateOnly.withZoneSameInstant(utc);
    ZonedDateTime utcWeekStart = parisTimeStartOfWeek.withZoneSameInstant(utc);
    // print…
    System.out.println("UTC  : " + utcTime.format(isoLDT));
    System.out.println(" --> " + utcTimeTilHour.format(isoLDT));
    System.out.println(" --> " + utcDateOnly.format(isoLDT));
    System.out.println(" --> " + utcWeekStart.format(isoLDT));
}

This example will output

Paris: 2022-05-08 21:43:20.0
 --> 2022-05-08 21:00:00.0
 --> 2022-05-08 00:00:00.0
 --> 2022-05-02 00:00:00.0
UTC  : 2022-05-08 19:43:20.0
 --> 2022-05-08 19:43:20.0
 --> 2022-05-07 22:00:00.0
 --> 2022-05-01 22:00:00.0

And if you really have a Timestamp only and you would have to extract the millis in order to create an Instant… That's not necessary anymore, there is a method now for legacy compatibility, that is Timestamp.toInstant().

deHaar
  • 17,687
  • 10
  • 38
  • 51
  • This works, and it solves the original question. However I've added timezone to it. So the end result should be the UTC time according to a timezone, we can use "Europe/Paris" as example. See the OP. Thank you very much. – TheStranger May 16 '22 at 11:26
  • @Ben Subtracting two hours would **not** result in Paris time… I added a possibility of shifting offsets in order to find your desired results, but please note **they don't have anything to do with Paris**. At least not with the capital of France! – deHaar May 16 '22 at 11:53
  • I don't understand.. The issue is that I need to use the time period in the Database query where the timestamps is UTC. In order to get data from today when I'm in Paris I would have to request data from 2022-05-15 22:00:00.0 to 2022-05-16 22:00:00.0. That's a day in Paris in UTC time... – TheStranger May 16 '22 at 11:57
  • That's weird because Paris is in GMT+2 at the moment, which is UTC+2. I think a zone shift would require hour addition rather than hour subtraction. You can find that out yourself, create a `ZoneId paris = ZoneId.of("Europe/Paris")` and use it in `ZonedDateTime parisTime = utcTime.withZoneSameInstant(paris)`, then check its values… – deHaar May 16 '22 at 12:01
  • Yes, if you have 19:00 in UTC and you need to transfer it to local time in Paris you'll have 21:00. But in this case you have 19:00 local time in paris, and need to convert to UTC so that should give you 17:00. But I can't simply say +2 or -2, because the timezone is dynamic. – TheStranger May 16 '22 at 12:04
  • 1
    OK, so your `Timestamp` is actually in Paris and not in UTC but you want to shift it to UTC and use the values in a db query? – deHaar May 16 '22 at 12:05
  • Yes, that's correct. – TheStranger May 16 '22 at 12:06
  • OK, then this whole misunderstanding was caused by mixing up zones and times: `Timestamp time = new Timestamp(1652039000000L);` is not the time in Paris you posted, but `"2022-05-08 21:43:20.0"`, which confused me a lot. – deHaar May 16 '22 at 12:14
  • I'm sorry you are correct. That was my mistake. – TheStranger May 16 '22 at 12:17
  • 1
    OK, then see my edit, should do what you desire now… Hint: Be as exact as possible when asking here, I think your question could have got upvotes but didn't because it was hard to understand what you wanted ;-) – deHaar May 16 '22 at 12:18
  • 1
    Perfect, thank you very much. Yes, I will work on it, it was a bit messy. I'll try to be more precise next time. Thank u once again. – TheStranger May 16 '22 at 12:29
  • 1
    You're welcome, makes me glad the solution works for you! – deHaar May 16 '22 at 12:32
0

Use timeStamp.toLocalDateTime().toLocalDate(); for converting TimeStamp to LocalDate then get start of week by following code:

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
    public class Main {
        public static void main(String[] args) {
            LocalDate date = LocalDate.of(2022, 5, 15);
            date = date.with(nextNthDayOfWeek(0, DayOfWeek.MONDAY));
            System.out.println("date = " + date); 
        }
    
        public static TemporalAdjuster nextNthDayOfWeek(int n, DayOfWeek dayOfWeek) {
            return temporal -> {
                Temporal next = temporal.with(TemporalAdjusters.next(dayOfWeek));
                return next.plus(n - 1, ChronoUnit.WEEKS);
            };
        }
    }

Java 8: Find nth DayOfWeek after specific day of month

Eskandar Abedini
  • 2,090
  • 2
  • 13
  • 3
    How is this connected to the actual question? That question is about a timestamp and how to extract stuff from it, not about `LocalDate` – RealSkeptic May 16 '22 at 10:48