Home > Mobile >  Get the start and end timestamp of the given timestamp in java
Get the start and end timestamp of the given timestamp in java

Time:11-19

I had a timestamp in Unix with milliseconds, now I need the start of the day and end of the day with milliseconds for the same given timestamp.

Eg:  1637293359000 - Given timestamp
Start of the day to be 1637280000000
End of the day to be 1637323199000

CodePudding user response:

In System default timezone you could try like this

    ZoneId zoneId = ZoneId.systemDefault();
    long timestamp = 1637293359000L;
    LocalDate date = Instant.ofEpochMilli(timestamp).atZone(zoneId).toLocalDate();
    LocalDateTime startDay = date.atStartOfDay();
    LocalDateTime endDay = date.atTime(LocalTime.MAX);
    System.out.println(startDay);
    System.out.println(endDay);
    long startDayLongValue = startDay.atZone(zoneId).toInstant().toEpochMilli();
    long endDayLongValue = endDay.atZone(zoneId).toInstant().toEpochMilli();
    System.out.println(startDayLongValue);
    System.out.println(endDayLongValue);

CodePudding user response:

We can achieve this using DateTime

import org.joda.time.DateTime;

long timestamp = 1629454215381L;
DateTime dateTime=new DateTime(timestamp ); 

long StartOfDayMillis = dateTime.withMillis(System.currentTimeMillis()).withTimeAtStartOfDay().getMillis();
long EndOfDayMillis = dateTime.withMillis(StartOfDayMillis).plusDays(1).minusSeconds(1).getMillis();

CodePudding user response:

tl;dr

Here is the complete code to a record representing the day of a specified moment as seen in a particular time zone. A static factory method contains our logic.

package work.basil.example;

import java.time.*;
import java.util.Objects;

public record DayInMillis( long start , long end )
{
    public static DayInMillis from ( final long moment , final ZoneId zoneId )
    {
        Objects.requireNonNull( zoneId );

        Instant instant = Instant.ofEpochMilli( moment );
        ZonedDateTime zdt = instant.atZone( zoneId );
        LocalDate ld = zdt.toLocalDate();
        ZonedDateTime start = ld.atStartOfDay( zoneId );
        ZonedDateTime end = ld.plusDays( 1 ).atStartOfDay( zoneId );
        Instant startInstant = start.toInstant();
        Instant endInstant = end.toInstant();
        long startMilli = startInstant.toEpochMilli();
        long endMilli = endInstant.toEpochMilli();

        System.out.println( "instant = "   instant );
        System.out.println( "zdt = "   zdt );
        System.out.println( "start/end = "   start   "/"   end );
        System.out.println( "startInstant/endInstant = "   startInstant   "/"   endInstant );
        System.out.println( "startMilli/endMilli = "   startMilli   "/"   endMilli );
        System.out.println( "Duration (not necessarily 24 hours): "   Duration.between( startInstant , endInstant ) );

        return new DayInMillis( startMilli , endMilli );
    }
}

Example usage:

DayInMillis.from( 1_637_293_359_000L , ZoneId.of( "Asia/Tokyo" ) )

When run.

instant = 2021-11-19T03:42:39Z
zdt = 2021-11-19T12:42:39 09:00[Asia/Tokyo]
start/end = 2021-11-19T00:00 09:00[Asia/Tokyo]/2021-11-20T00:00 09:00[Asia/Tokyo]
startInstant/endInstant = 2021-11-18T15:00:00Z/2021-11-19T15:00:00Z
startMilli/endMilli = 1637247600000/1637334000000
Duration (not necessarily 24 hours): PT24H
dayInMillis = DayInMillis[start=1637247600000, end=1637334000000]

Parse count of seconds

Parse your input count of milliseconds since epoch of first moment of 1970 in UTC as a Instant object.

Instant instant = Instant.ofEpochMilli( 1_637_293_359_000L ) ;

Adjust into time zone

Specify the time zone by which you want to perceive dates.

ZoneId z = ZoneId.of( "America/Edmonton" ) ;

Adjust from UTC (an offset of zero hours-minutes-seconds) to that time zone.

ZonedDateTime zdt = instant.atZone( z ) ;

Get the date

Extract the date-only portion.

LocalDate ld = zdt.toLocalDate() ;

Start of day

Let java.time determine the first moment of the day. Never assume the day starts at 00:00. Some dates in some zones may start at another time such as 01:00.

ZonedDateTime start = ld.atStartOfDay( z ) ;

Half-Open

The last moment of the day is infinitely divisible. For this and other reasons, spans of time are usually best defined using Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive. This means the span of a day starts at the first moment of the day and runs up to, but does not include, the first moment of the following day.

ZonedDateTime end = ld.plusDays( 1 ).atStartOfDay( z ) ;

Now we have the span covered by a pair of ZonedDateTime objects. But you want to get a count of milliseconds since epoch for both of those.

Tracking count-from-epoch is awkward

Let me say, I do not recommend using a count-since-epoch for time-keeping. The values are inherently ambiguous as to both epoch and granularity. Furthermore, using such counts makes debugging difficult and errors hard to spot, as such values are meaningless to human readers.

ISO 8601

Instead, I suggest communicating such values textually in standard ISO 8601 format. The java.time classes use ISO 8601 formats by default when parsing/generating text.

String outputStart = start.toInstant().toString();
String outputEnd = end.toInstant().toString();

Milliseconds since epoch

But if you insist on the count of milliseconds, first extract Instant objects from our ZonedDateTime objects, effectively adjusting to UTC (offset of zero).

Instant startInstant = start.toInstant() ;
Instant endInstant = end.toInstant() ;

Interrogate for a count of milliseconds since epoch.

long startMilli = startInstant.toEpochMilli() ;
long endMilli = endInstant.toEpochMilli() ;

Avoid LocalDateTime for this problem

Notice that at no point did we use the LocalDateTime class. That class purposely lacks the context of a time zone or offset-from-UTC. So LocalDateTime cannot represent a moment, is not a point on the timeline. That makes LocalDateTime irrelevant to the problem at hand.

  • Related