Skip to content

Instantly share code, notes, and snippets.

@bdkosher
Created May 1, 2020 18:42
Show Gist options
  • Save bdkosher/109b6f3a428b81d684077618a03eb952 to your computer and use it in GitHub Desktop.
Save bdkosher/109b6f3a428b81d684077618a03eb952 to your computer and use it in GitHub Desktop.
import java.time.temporal.*;
import static java.time.Month.OCTOBER;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.YEAR;
/**
* Temporal fields that are commonly used within the Federal government.
*
* More fields may be added in the future (e.g. Leave Year, Bi-Weekly Pay Period)
*/
public enum FederalField implements TemporalField {
/**
* The fiscal year is the accounting period for the federal government which begins on October 1 and ends on
* September 30. The fiscal year is designated by the calendar year in which it ends; for example, fiscal year 2013
* begins on October 1, 2012 and ends on September 30, 2013.
*/
FISCAL_YEAR {
@Override
public TemporalUnit getBaseUnit() {
return YEAR.getBaseUnit();
}
@Override
public TemporalUnit getRangeUnit() {
return YEAR.getRangeUnit();
}
@Override
public ValueRange range() {
return YEAR.range();
}
@Override
public boolean isSupportedBy(TemporalAccessor temporalAccessor) {
return YEAR.isSupportedBy(temporalAccessor);
}
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporalAccessor) {
return YEAR.rangeRefinedBy(temporalAccessor);
}
@Override
public long getFrom(TemporalAccessor temporalAccessor) {
long year = temporalAccessor.get(YEAR);
long month = temporalAccessor.get(MONTH_OF_YEAR);
return month >= OCTOBER.getValue() ? year + 1 : year;
}
@Override
public <R extends Temporal> R adjustInto(R temporal, long newFiscalYear) {
long newYear = temporal.get(MONTH_OF_YEAR) >= OCTOBER.getValue() ? newFiscalYear - 1 : newFiscalYear;
return (R) temporal.with(YEAR, newYear);
}
},
/**
* As with calendar years, the fiscal year is also divided into quarters. Quarter 1 of each Fiscal Year begins
* Oct 1st. Quarter 2 starts January 1st. Quarter 3 on April 1st (no joke). And Quarter 4 begins on August 1st.
*/
FISCAL_QUARTER {
@Override
public TemporalUnit getBaseUnit() {
return IsoFields.QUARTER_OF_YEAR.getBaseUnit();
}
@Override
public TemporalUnit getRangeUnit() {
return IsoFields.QUARTER_OF_YEAR.getRangeUnit();
}
@Override
public ValueRange range() {
return IsoFields.QUARTER_OF_YEAR.range();
}
@Override
public boolean isSupportedBy(TemporalAccessor temporalAccessor) {
return IsoFields.QUARTER_OF_YEAR.isSupportedBy(temporalAccessor);
}
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporalAccessor) {
return IsoFields.QUARTER_OF_YEAR.rangeRefinedBy(temporalAccessor);
}
@Override
public long getFrom(TemporalAccessor temporalAccessor) {
long actualQuarter = temporalAccessor.get(IsoFields.QUARTER_OF_YEAR);
return actualQuarter % 4 + 1;
}
@Override
public <R extends Temporal> R adjustInto(R temporal, long newFyQuarter) {
long newQuarter = newFyQuarter == 1 ? 4 : newFyQuarter - 1;
return (R) temporal.with(IsoFields.QUARTER_OF_YEAR, newQuarter);
}
};
/**
* Always returns true as the fields enumerated are all date based.
*
* @return true
*/
@Override
public boolean isDateBased() {
return true;
}
/**
* Always returns false as the fields enumerated are all date based.
*
* @return false
*/
@Override
public boolean isTimeBased() {
return false;
}
}
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.time.Month;
import java.time.YearMonth;
import java.time.temporal.IsoFields;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.time.Month.*;
import static org.assertj.core.api.Assertions.assertThat;
public class FederalFieldTest {
@Test
void fiscal_year_on_the_first_for_every_month() {
final int year = 2018;
IntStream.rangeClosed(JANUARY.getValue(), SEPTEMBER.getValue()).mapToObj(Month::of).forEachOrdered(month -> {
assertThat(LocalDate.of(year, month, 1).get(FederalField.FISCAL_YEAR)).isEqualTo(year);
assertThat(YearMonth.of(year, month).get(FederalField.FISCAL_YEAR)).isEqualTo(year);
});
IntStream.rangeClosed(OCTOBER.getValue(), DECEMBER.getValue()).mapToObj(Month::of).forEachOrdered(month -> {
assertThat(LocalDate.of(year, month, 1).get(FederalField.FISCAL_YEAR)).isEqualTo(year + 1);
assertThat(YearMonth.of(year, month).get(FederalField.FISCAL_YEAR)).isEqualTo(year + 1);
});
}
@Test
void fiscal_year_transitions() {
final int year = 2016;
assertThat(LocalDate.of(year, SEPTEMBER, 28).get(FederalField.FISCAL_YEAR)).isEqualTo(year);
assertThat(LocalDate.of(year, SEPTEMBER, 30).get(FederalField.FISCAL_YEAR)).isEqualTo(year);
assertThat(LocalDate.of(year, OCTOBER, 1).get(FederalField.FISCAL_YEAR)).isEqualTo(year + 1);
assertThat(LocalDate.of(year, OCTOBER, 2).get(FederalField.FISCAL_YEAR)).isEqualTo(year + 1);
assertThat(LocalDate.of(year, DECEMBER, 30).get(FederalField.FISCAL_YEAR)).isEqualTo(year + 1);
assertThat(LocalDate.of(year, DECEMBER, 31).get(FederalField.FISCAL_YEAR)).isEqualTo(year + 1);
assertThat(LocalDate.of(year, JANUARY, 1).get(FederalField.FISCAL_YEAR)).isEqualTo(year);
assertThat(LocalDate.of(year, JANUARY, 2).get(FederalField.FISCAL_YEAR)).isEqualTo(year);
}
@Test
void adjusting_into_fiscal_year_no_change() {
LocalDate oct1 = LocalDate.of(2018, OCTOBER, 1);
LocalDate oct1fy19 = oct1.with(FederalField.FISCAL_YEAR, 2019);
assertThat(oct1fy19).isEqualTo(oct1);
LocalDate dec31 = LocalDate.of(2018, DECEMBER, 31);
LocalDate dec31fy19 = dec31.with(FederalField.FISCAL_YEAR, 2019);
assertThat(dec31fy19).isEqualTo(dec31);
}
@Test
void adjusting_into_fiscal_year_changes_year() {
LocalDate sep30 = LocalDate.of(2018, SEPTEMBER, 30);
LocalDate sep30fy19 = sep30.with(FederalField.FISCAL_YEAR, 2019);
assertThat(sep30fy19).isEqualTo(LocalDate.of(2019, SEPTEMBER, 30));
LocalDate jan1 = LocalDate.of(2018, JANUARY, 1);
LocalDate jan1fy19 = jan1.with(FederalField.FISCAL_YEAR, 2019);
assertThat(jan1fy19).isEqualTo(LocalDate.of(2019, JANUARY, 1));
}
@Test
void fiscal_year_quarter_on_the_first_for_every_month() {
final int year = 2018;
IntStream.rangeClosed(JANUARY.getValue(), MARCH.getValue()).mapToObj(Month::of).forEachOrdered(month -> {
assertThat(LocalDate.of(year, month, 1).get(FederalField.FISCAL_QUARTER)).isEqualTo(2);
assertThat(YearMonth.of(year, month).get(FederalField.FISCAL_QUARTER)).isEqualTo(2);
});
IntStream.rangeClosed(APRIL.getValue(), JUNE.getValue()).mapToObj(Month::of).forEachOrdered(month -> {
assertThat(LocalDate.of(year, month, 1).get(FederalField.FISCAL_QUARTER)).isEqualTo(3);
assertThat(YearMonth.of(year, month).get(FederalField.FISCAL_QUARTER)).isEqualTo(3);
});
IntStream.rangeClosed(JULY.getValue(), SEPTEMBER.getValue()).mapToObj(Month::of).forEachOrdered(month -> {
assertThat(LocalDate.of(year, month, 1).get(FederalField.FISCAL_QUARTER)).isEqualTo(4);
assertThat(YearMonth.of(year, month).get(FederalField.FISCAL_QUARTER)).isEqualTo(4);
});
IntStream.rangeClosed(OCTOBER.getValue(), DECEMBER.getValue()).mapToObj(Month::of).forEachOrdered(month -> {
assertThat(LocalDate.of(year, month, 1).get(FederalField.FISCAL_QUARTER)).isEqualTo(1);
assertThat(YearMonth.of(year, month).get(FederalField.FISCAL_QUARTER)).isEqualTo(1);
});
}
@Test
void fiscal_year_quarter_transitions() {
final int year = 2016;
assertThat(LocalDate.of(year, SEPTEMBER, 28).get(FederalField.FISCAL_QUARTER)).isEqualTo(4);
assertThat(LocalDate.of(year, SEPTEMBER, 30).get(FederalField.FISCAL_QUARTER)).isEqualTo(4);
assertThat(LocalDate.of(year, OCTOBER, 1).get(FederalField.FISCAL_QUARTER)).isEqualTo(1);
assertThat(LocalDate.of(year, OCTOBER, 2).get(FederalField.FISCAL_QUARTER)).isEqualTo(1);
assertThat(LocalDate.of(year, DECEMBER, 30).get(FederalField.FISCAL_QUARTER)).isEqualTo(1);
assertThat(LocalDate.of(year, DECEMBER, 31).get(FederalField.FISCAL_QUARTER)).isEqualTo(1);
assertThat(LocalDate.of(year, JANUARY, 1).get(FederalField.FISCAL_QUARTER)).isEqualTo(2);
assertThat(LocalDate.of(year, JANUARY, 2).get(FederalField.FISCAL_QUARTER)).isEqualTo(2);
assertThat(LocalDate.of(year, MARCH, 30).get(FederalField.FISCAL_QUARTER)).isEqualTo(2);
assertThat(LocalDate.of(year, MARCH, 31).get(FederalField.FISCAL_QUARTER)).isEqualTo(2);
assertThat(LocalDate.of(year, APRIL, 1).get(FederalField.FISCAL_QUARTER)).isEqualTo(3);
assertThat(LocalDate.of(year, APRIL, 2).get(FederalField.FISCAL_QUARTER)).isEqualTo(3);
assertThat(LocalDate.of(year, JUNE, 29).get(FederalField.FISCAL_QUARTER)).isEqualTo(3);
assertThat(LocalDate.of(year, JUNE, 30).get(FederalField.FISCAL_QUARTER)).isEqualTo(3);
assertThat(LocalDate.of(year, JULY, 1).get(FederalField.FISCAL_QUARTER)).isEqualTo(4);
assertThat(LocalDate.of(year, JULY, 2).get(FederalField.FISCAL_QUARTER)).isEqualTo(4);
}
@Test
void adjusting_into_fiscal_quarter_no_change() {
final int year = 2017;
LocalDate oct1 = LocalDate.of(year, OCTOBER, 1);
LocalDate oct1q1 = oct1.with(FederalField.FISCAL_QUARTER, 1);
assertThat(oct1q1).isEqualTo(oct1);
LocalDate dec31 = LocalDate.of(year, DECEMBER, 31);
LocalDate dec31q1 = dec31.with(FederalField.FISCAL_QUARTER, 1);
assertThat(dec31q1).isEqualTo(dec31);
LocalDate jan1 = LocalDate.of(year, JANUARY, 1);
LocalDate jan1q2 = jan1.with(FederalField.FISCAL_QUARTER, 2);
assertThat(jan1q2).isEqualTo(jan1q2);
LocalDate mar31 = LocalDate.of(year, MARCH, 31);
LocalDate mar31q2 = mar31.with(FederalField.FISCAL_QUARTER, 2);
assertThat(mar31q2).isEqualTo(mar31);
LocalDate apr1 = LocalDate.of(year, APRIL, 1);
LocalDate apr1q3 = apr1.with(FederalField.FISCAL_QUARTER, 3);
assertThat(apr1q3).isEqualTo(apr1);
LocalDate jun30 = LocalDate.of(year, JUNE, 30);
LocalDate jun30q3 = jun30.with(FederalField.FISCAL_QUARTER, 3);
assertThat(jun30q3).isEqualTo(jun30);
LocalDate jul1 = LocalDate.of(year, JULY, 1);
LocalDate jul1q4 = jul1.with(FederalField.FISCAL_QUARTER, 4);
assertThat(jul1q4).isEqualTo(jul1);
LocalDate sep30 = LocalDate.of(year, SEPTEMBER, 30);
LocalDate sep30q4 = sep30.with(FederalField.FISCAL_QUARTER, 4);
assertThat(sep30q4).isEqualTo(sep30);
}
@Test
void adjusting_into_fiscal_quarter_changes_month() {
final int year = 2018;
assertThat(YearMonth.of(year, JANUARY).with(FederalField.FISCAL_QUARTER, 1))
.isEqualTo(YearMonth.of(year, OCTOBER));
assertThat(YearMonth.of(year, FEBRUARY).with(FederalField.FISCAL_QUARTER, 1))
.isEqualTo(YearMonth.of(year, NOVEMBER));
assertThat(YearMonth.of(year, MARCH).with(FederalField.FISCAL_QUARTER, 1))
.isEqualTo(YearMonth.of(year, DECEMBER));
assertThat(YearMonth.of(year, OCTOBER).with(FederalField.FISCAL_QUARTER, 4))
.isEqualTo(YearMonth.of(year, JULY));
assertThat(YearMonth.of(year, NOVEMBER).with(FederalField.FISCAL_QUARTER, 4))
.isEqualTo(YearMonth.of(year, AUGUST));
assertThat(YearMonth.of(year, DECEMBER).with(FederalField.FISCAL_QUARTER, 4))
.isEqualTo(YearMonth.of(year, SEPTEMBER));
assertThat(YearMonth.of(year, JANUARY).with(FederalField.FISCAL_QUARTER, 3))
.isEqualTo(YearMonth.of(year, APRIL));
assertThat(YearMonth.of(year, FEBRUARY).with(FederalField.FISCAL_QUARTER, 3))
.isEqualTo(YearMonth.of(year, MAY));
assertThat(YearMonth.of(year, MARCH).with(FederalField.FISCAL_QUARTER, 3))
.isEqualTo(YearMonth.of(year, JUNE));
assertThat(YearMonth.of(year, OCTOBER).with(FederalField.FISCAL_QUARTER, 2))
.isEqualTo(YearMonth.of(year, JANUARY));
assertThat(YearMonth.of(year, NOVEMBER).with(FederalField.FISCAL_QUARTER, 2))
.isEqualTo(YearMonth.of(year, FEBRUARY));
assertThat(YearMonth.of(year, DECEMBER).with(FederalField.FISCAL_QUARTER, 2))
.isEqualTo(YearMonth.of(year, MARCH));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment