Home > Software engineering >  Way to get end points of a time interval based on a date?
Way to get end points of a time interval based on a date?

Time:01-21

I think I can do this on my own but I don't want to reinvent a wheel (especially regarding date arithmetic) if I don't have to.

I'm making a swing application that has a drop down where a user can select a time interval with the options being All, Today, This Week, This Month, This Quarter, This Year, Last Week, Last Month, Last Quarter, Last Year. When a user selects one of these I want to calculate the interval.

For instance, today is 1/19/2022. If someone selected This Week, my startDate would be 2022-01-16 00:00:00 and my endDate would be 2022-01-22 11:59:59 (or perhaps it would make more sense to be 2022-01-23 00:00:00?)

For the All Selection I've already implented a method where my startDate is January 1, 1970 and my endDate is a few years into the future from the current time. I also was able to do Today by myself by just getting todays date and adjusting the times from midnight to midnight.

But for all these other options I don't know if there's already a library or such that has calculated them that I could leverage. It's been a while since I touched java in general and don't know the ecosystem well.

Also important to this is that the endDate and startDates are either java.util.Date type or a sublclass of it as I need to integrate it with code that is counting on that.

Any pointers would be greatly appreciated.

CodePudding user response:

I would use java.time.LocalDate, which you can easily obtain from java.util.Date and convert back and forth if needed.

Here is how you can get the start of the current week using LocalDate (using the US locale, you can use something else if the start of the week is different)

LocalDate now = LocalDate.now();
TemporalField fieldUS = WeekFields.of(Locale.US).dayOfWeek();
System.out.println(now.with(fieldUS, 1)); 

You can find how to do the rest of your requirements from other StackOverflow posts with a little searching.

Here is how you can convert a Date to LocalDate

Date date = new Date();
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

And convert from LocalDate to Date

LocalDate localDate = LocalDate.now();
Date date = Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());

CodePudding user response:

Time zone

You said:

For instance, today is 1/19/2022. If someone selected This Week, my startDate would be 2022-01-16 00:00:00

Be aware that determining a moment requires a time zone. The time 00:00 on the 16th happened several hours earlier in Tokyo Japan than in Toledo Ohio US.

Also, some dates in some time zones, the day does not begin at 00:00. Rather than assume, let java.time determine the first moment of the day.

ZoneId zTokyo = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime todayStartTokyo = ZonedDateTime.now( zTokyo ).toLocalDate().atStartOfDay( zTokyo ) ;

Months

For a month, use java.time.YearMonth.

ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" ) ;
LocalDate ld = LocalDate.of( 2022 , 1 , 19 ) ;
YearMonth ym = YearMonth.from( ld ) ;

Determine date range.

LocalDate dateStart = yw.atDay( 1 ) ;
LocalDate dateEnd = yw.plusMonths( 1 ) ;

Determine moments.

ZonedDateTime zdtStart = dateStart.atStartOfDay( zAuckland ) ;
ZonedDateTime zdtEnd = dateEnd.atStartOfDay( zAuckland ) ;

Quarters

If your definition of quarters agrees with that of ISO 8601, I suggest adding the ThreeTen-Extra library to your project for its org.threeten.extra.Quarter enum and org.threeten.extra.YearQuarter class.

Again, the definition of week used in that class conforms with ISO 8601. If your definition differs, this class will not work for you. An ISO 8601 week starts on Monday, and runs through Sunday, with week # 1 of the year having the first Thursday of the calendar year, for a resulting 52 or 53 full-seven-day weeks per week-based-year.

LocalDate ld = LocalDate.of( 2022 , 1 , 19 ) ;
YearQuarter yq = YearQuarter.from( localDate ) ;
LocalDate yqStart = yq.atDay( 1 ) ;
LocalDate yqEnd = yq.plusQuarters( 1 ).atDay( 1 ) ;

Same range in moments:

ZoneId zTunis = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdtStart = yqStart.atStartOfDay( zTunis ) ;
ZonedDateTime zdtEnd = yqEnd.atStartOfDay( zTunis ) ;

Weeks

As with quarters, for working with weeks I suggest adding the ThreeTen-Extra library for its org.threeten.extra.YearWeek class. The built-in java.time do have some week features, but they are limited.

ZoneId zEdmonton = ZoneId.of( "America/Edmonton" ) ;
LocalDate todayEdmonton = LocalDate.now( zEdmonton ) ;
YearWeek yw = YearWeek.from( todayEdmonton ) ;

Or, just:

YearWeek yw = YearWeek.now( zEdmonton ) ;

To determine date range:

LocalDate weekStart = yw.atDay( DayOfWeek.MONDAY ) ;
LocalDate weekEnd = yw.plusWeeks( 1 ).atDay( DayOfWeek.MONDAY ) ;

To determine a range of moments, use same code seen above, calling atStartOfDay.

  •  Tags:  
  • Related