nhaarman
nhaarman

Reputation: 100398

Jodatime start of day and end of day

I want to create an interval between the beginning of the week, and the end of the current week.

I have the following code, borrowed from this answer:

private LocalDateTime calcNextSunday(LocalDateTime d) {
    if (d.getDayOfWeek() > DateTimeConstants.SUNDAY) {
        d = d.plusWeeks(1);
    }
    return d.withDayOfWeek(DateTimeConstants.SUNDAY);
}

private LocalDateTime calcPreviousMonday(LocalDateTime d) {
    if (d.getDayOfWeek() < DateTimeConstants.MONDAY) {
        d = d.minusWeeks(1);
    }
    return d.withDayOfWeek(DateTimeConstants.MONDAY);
}

But now I want the Monday LocalDateTime to be at 00:00:00, and the Sunday LocalDateTime at 23:59:59. How would I do this?

Upvotes: 52

Views: 55997

Answers (7)

TheRueger
TheRueger

Reputation: 2578

A simple way is:

d.millisOfDay().withMaximumValue();

Upvotes: 101

hd1
hd1

Reputation: 34657

DateTime.now().withTimeAtStartOfDay(); // start of day
DateTime.now().plusDays(1).withTimeAtStartOfDay().minusSeconds(1); // end of day

Upvotes: 0

Cory Roy
Cory Roy

Reputation: 5609

With Kotlin you could write an extension function:

fun DateTime.withTimeAtEndOfDay() : DateTime = this.withTime(23,59,59,999)

This would allow you to write:

d.withDayOfWeek(DateTimeConstants.SUNDAY).withTimeAtEndOfDay()

Upvotes: 2

Nikola Mihajlović
Nikola Mihajlović

Reputation: 2465

begin = d
    // Go to previous or same Sunday
    .with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY))
    // Beginning of day
    .truncatedTo(ChronoUnit.DAYS)

end = d
    // Go to next Sunday
    .with(TemporalAdjusters.next(DayOfWeek.SUNDAY))
    // Beginning of day
    .truncatedTo(ChronoUnit.DAYS)

I also think it is a bad idea to represent the end of week interval with small amount of time before the actual, exclusive end. It is better to treat begin as inclusive, and end as exclusive instead (when doing comparisons etc.).

Upvotes: 0

GreeneCreations
GreeneCreations

Reputation: 1242

For those coming here looking for the answer for "js-joda", you have two options depending on what you're looking to accomplish

Option 1: You want the start of the day in the same timezone

Since you've chosen to calculate your times based on an instant in time in relation to a timezone, you should use ZonedDateTime:

import { ZonedDateTime, LocalDate, ZoneId, DateTimeFormatter} from "js-joda";
import 'js-joda-timezone';

const nowInNewYorkCity = ZonedDateTime.now(ZoneId.of("America/New_York"))
const startOfTodayInNYC = nowInNewYorkCity.truncatedTo(ChronoUnit.DAYS);
console.log(startOfTodayInNYC.toString()) // Prints "2019-04-15T00:00-04:00[America/New_York]"
// And if you want to print it in ISO format
console.log(startOfTodayInNYC.format(DateTimeFormatter.ISO_INSTANT)) // "2019-04-14T04:00:00Z"

Option 2: You know the exact day that you want to get the time for

Then you can use the following methods off of LocalDate to derive the relative time (i.e. ZonedDateTime) you'd like:

    atStartOfDay(): LocalDateTime
    atStartOfDay(zone: ZoneId): ZonedDateTime
    atStartOfDayWithZone(zone: ZoneId): ZonedDateTime

Option 3: I want just the day the instant occurred on

Notice with this code, you get the day that it would be relative to where you are. So for those in New York City, it's "2019-04-14" and for those in London it would be "2019-04-15" (which is great!) because the instant in time was during the period of time where it's actually tomorrow in London ("2019-04-15T00:00:05Z"). Pretend that you were calling someone in London from NYC, and the Londoner would say, "geez, why are you calling me so early... it's 5 seconds past midnight."

import { ZonedDateTime, LocalDate, ZoneId} from "js-joda";
import 'js-joda-timezone';

const aTimeWhenLondonIsAlreadyInTomorrow = "2019-04-15T00:00:05.000Z";
const inBetweenTimeInLondon = ZonedDateTime.parse(aTimeWhenLondonIsAlreadyInTomorrow);
const inBetweenTimeInNYC = inBetweenTimeInLondon.withZoneSameInstant(ZoneId.of("America/New_York"))
const dayInLondon = inBetweenTimeInLondon.toLocalDate();
const dayInNYC = inBetweenTimeInNYC.toLocalDate();
console.log(inBetweenTimeInLondon.toString()); // "2019-04-15T00:00:05Z"
console.log(dayInLondon.toString()); // "2019-04-15"
console.log(inBetweenTimeInNYC.toString()) // "2019-04-14T20:00:05-04:00[America/New_York]"
console.log(dayInNYC.toString()); // "2019-04-14"

References: https://js-joda.github.io/js-joda/class/src/LocalDate.js~LocalDate.html#instance-method-atStartOfDayWithZone

Upvotes: 1

JodaStephen
JodaStephen

Reputation: 63385

You can use the withTime method:

 d.withTime(0, 0, 0, 0);
 d.withTime(23, 59, 59, 999);

Same as Peter's answer, but shorter.

Upvotes: 156

Peter Svensson
Peter Svensson

Reputation: 6173

How about:

private LocalDateTime calcNextSunday(LocalDateTime d) {
    return d.withHourOfDay(23).withMinuteOfHour(59).withSecondOfMinute(59).withDayOfWeek(DateTimeConstants.SUNDAY);
}

private LocalDateTime calcPreviousMonday(final LocalDateTime d) {
    return d.withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withDayOfWeek(DateTimeConstants.MONDAY);
}

Upvotes: 25

Related Questions