Documentation ¶
Overview ¶
Package jdcal provides conversions from dates on the Julian calendar to the Gregorian calendar and vice versa, and knows about zones (geographical locations) where such switches occurred, and at which dates. Holidays that depend on moon phases (e.g., Easter) can be computed.
Furthermore helper functions are provided for small tasks, such as: date validation, is a year a leap year (which depends on the calendar type), comparisons between dates (before/after/equal), advancing a date while honoring leap years.
The distribution also contains a CLI main/jdcal/jdcal.go which provides a command line interface.
Index ¶
- Constants
- Variables
- type CalendarYear
- type ConversionAlgorithm
- type ConversionEntry
- type Date
- func (d Date) Advance() Date
- func (d Date) After(other Date) (bool, error)
- func (d Date) AfterOrEqual(other Date) (bool, error)
- func (d Date) AsTime() (tm time.Time, err error)
- func (d Date) Backward() Date
- func (d Date) Before(other Date) (bool, error)
- func (d Date) BeforeOrEqual(other Date) (bool, error)
- func (d Date) Convert() (Date, error)
- func (d Date) Equal(other Date) (bool, error)
- func (d Date) Forward() Date
- func (d Date) InZone(z ZoneEntry) (bool, error)
- func (d Date) IsSet() bool
- func (d Date) Ordinal() Ordinal
- func (d Date) String() string
- func (d Date) Valid() error
- func (d Date) Weekday() (wd time.Weekday, err error)
- type Holiday
- type MD
- type MonthProgression
- type Ordinal
- type Type
- type YMD
- type Year
- type ZoneEntry
Constants ¶
const ( StartProgressionYear = -500 EndProgressionYear = 2100 )
Variables ¶
var ConversionTable = [...]ConversionEntry{ { JDate: Date{Year: -501, Month: time.March, Day: 5, Type: Julian}, GDate: Date{Year: -501, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: -501, Month: time.March, Day: 6, Type: Julian}, GDate: Date{Year: -501, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: -301, Month: time.March, Day: 3, Type: Julian}, GDate: Date{Year: -301, Month: time.February, Day: 27, Type: Gregorian}, }, { JDate: Date{Year: -301, Month: time.March, Day: 4, Type: Julian}, GDate: Date{Year: -301, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: -301, Month: time.March, Day: 5, Type: Julian}, GDate: Date{Year: -301, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: -201, Month: time.March, Day: 2, Type: Julian}, GDate: Date{Year: -201, Month: time.February, Day: 27, Type: Gregorian}, }, { JDate: Date{Year: -201, Month: time.March, Day: 3, Type: Julian}, GDate: Date{Year: -201, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: -201, Month: time.March, Day: 4, Type: Julian}, GDate: Date{Year: -201, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: -101, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: -101, Month: time.February, Day: 27, Type: Gregorian}, }, { JDate: Date{Year: -101, Month: time.March, Day: 2, Type: Julian}, GDate: Date{Year: -101, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: -101, Month: time.March, Day: 3, Type: Julian}, GDate: Date{Year: -101, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: 100, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 100, Month: time.February, Day: 27, Type: Gregorian}, }, { JDate: Date{Year: 100, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 100, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: 100, Month: time.March, Day: 2, Type: Julian}, GDate: Date{Year: 100, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: 200, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 200, Month: time.February, Day: 27, Type: Gregorian}, }, { JDate: Date{Year: 200, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 200, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: 200, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 200, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: 300, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 300, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: 300, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 300, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: 300, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 300, Month: time.March, Day: 2, Type: Gregorian}, }, { JDate: Date{Year: 500, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 500, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: 500, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 500, Month: time.March, Day: 2, Type: Gregorian}, }, { JDate: Date{Year: 500, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 500, Month: time.March, Day: 3, Type: Gregorian}, }, { JDate: Date{Year: 600, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 600, Month: time.March, Day: 2, Type: Gregorian}, }, { JDate: Date{Year: 600, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 600, Month: time.March, Day: 3, Type: Gregorian}, }, { JDate: Date{Year: 600, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 600, Month: time.March, Day: 4, Type: Gregorian}, }, { JDate: Date{Year: 700, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 700, Month: time.March, Day: 3, Type: Gregorian}, }, { JDate: Date{Year: 700, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 700, Month: time.March, Day: 4, Type: Gregorian}, }, { JDate: Date{Year: 700, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 700, Month: time.March, Day: 5, Type: Gregorian}, }, { JDate: Date{Year: 900, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 900, Month: time.March, Day: 4, Type: Gregorian}, }, { JDate: Date{Year: 900, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 900, Month: time.March, Day: 5, Type: Gregorian}, }, { JDate: Date{Year: 900, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 900, Month: time.March, Day: 6, Type: Gregorian}, }, { JDate: Date{Year: 1000, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 1000, Month: time.March, Day: 5, Type: Gregorian}, }, { JDate: Date{Year: 1000, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 1000, Month: time.March, Day: 6, Type: Gregorian}, }, { JDate: Date{Year: 1000, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 1000, Month: time.March, Day: 7, Type: Gregorian}, }, { JDate: Date{Year: 1100, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 1100, Month: time.March, Day: 6, Type: Gregorian}, }, { JDate: Date{Year: 1100, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 1100, Month: time.March, Day: 7, Type: Gregorian}, }, { JDate: Date{Year: 1100, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 1100, Month: time.March, Day: 8, Type: Gregorian}, }, { JDate: Date{Year: 1300, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 1300, Month: time.March, Day: 7, Type: Gregorian}, }, { JDate: Date{Year: 1300, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 1300, Month: time.March, Day: 8, Type: Gregorian}, }, { JDate: Date{Year: 1300, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 1300, Month: time.March, Day: 9, Type: Gregorian}, }, { JDate: Date{Year: 1400, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 1400, Month: time.March, Day: 8, Type: Gregorian}, }, { JDate: Date{Year: 1400, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 1400, Month: time.March, Day: 9, Type: Gregorian}, }, { JDate: Date{Year: 1400, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 1400, Month: time.March, Day: 10, Type: Gregorian}, }, { JDate: Date{Year: 1500, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 1500, Month: time.March, Day: 9, Type: Gregorian}, }, { JDate: Date{Year: 1500, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 1500, Month: time.March, Day: 10, Type: Gregorian}, }, { JDate: Date{Year: 1500, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 1500, Month: time.March, Day: 11, Type: Gregorian}, }, { JDate: Date{Year: 1700, Month: time.February, Day: 18, Type: Julian}, GDate: Date{Year: 1700, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: 1700, Month: time.February, Day: 19, Type: Julian}, GDate: Date{Year: 1700, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: 1700, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 1700, Month: time.March, Day: 10, Type: Gregorian}, }, { JDate: Date{Year: 1700, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 1700, Month: time.March, Day: 11, Type: Gregorian}, }, { JDate: Date{Year: 1700, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 1700, Month: time.March, Day: 12, Type: Gregorian}, }, { JDate: Date{Year: 1800, Month: time.February, Day: 17, Type: Julian}, GDate: Date{Year: 1800, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: 1800, Month: time.February, Day: 18, Type: Julian}, GDate: Date{Year: 1800, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: 1800, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 1800, Month: time.March, Day: 11, Type: Gregorian}, }, { JDate: Date{Year: 1800, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 1800, Month: time.March, Day: 12, Type: Gregorian}, }, { JDate: Date{Year: 1800, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 1800, Month: time.March, Day: 13, Type: Gregorian}, }, { JDate: Date{Year: 1900, Month: time.February, Day: 16, Type: Julian}, GDate: Date{Year: 1900, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: 1900, Month: time.February, Day: 17, Type: Julian}, GDate: Date{Year: 1900, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: 1900, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 1900, Month: time.March, Day: 12, Type: Gregorian}, }, { JDate: Date{Year: 1900, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 1900, Month: time.March, Day: 13, Type: Gregorian}, }, { JDate: Date{Year: 1900, Month: time.March, Day: 1, Type: Julian}, GDate: Date{Year: 1900, Month: time.March, Day: 14, Type: Gregorian}, }, { JDate: Date{Year: 2100, Month: time.February, Day: 15, Type: Julian}, GDate: Date{Year: 2100, Month: time.February, Day: 28, Type: Gregorian}, }, { JDate: Date{Year: 2100, Month: time.February, Day: 16, Type: Julian}, GDate: Date{Year: 2100, Month: time.March, Day: 1, Type: Gregorian}, }, { JDate: Date{Year: 2100, Month: time.February, Day: 28, Type: Julian}, GDate: Date{Year: 2100, Month: time.March, Day: 13, Type: Gregorian}, }, { JDate: Date{Year: 2100, Month: time.February, Day: 29, Type: Julian}, GDate: Date{Year: 2100, Month: time.March, Day: 14, Type: Gregorian}, }, }
ConversionTable defines matching Julian and Gregorian dates. It is consulted by, e.g., Date.Convert(). The contained ConversionEntry's won't normally be of use outside of this module, but they are coded as exportable (as uppercase symbols) so they can be inspected.
This table reflects https://en.wikipedia.org/wiki/Conversion_between_Julian_and_Gregorian_calendars, original source: the Nautical almanac of the United Kingdom and United States (1961). This table however knows that year zero doesn't exist (we go 2BC, 1BC, 1AD, 2AD), therefore, years before 0 are generated one-off relative to the above source refrence.
var FullMoons = map[Year]MD{}/* 2599 elements not displayed */
FullMoons maps years to a month and day (MD) representing the first full moon beyond March 21st. The date points are relative to the Georgian calendar. Example:
md, ok := jdcal.FullMoons[1600] if !ok { log.Fatal("no full moon information for year 1600") } fmt.Println("first full moon beyond March 21st in the year 1600 is on", md) // 03/29
The data were obtained from https://astropixels.com/ephemeris/phasescat/phasescat.html Moon Phases Table courtesy of Fred Espenak, www.Astropixels.com.
The data here differ from www.Astropixels.com in that:
- Years are stated as BC or AD - so -3, -2, -1, 1, 2, 3, etc.. There is no year zero. Astropixels.com knows a year zero and has -2, -1, 0, 1, 2, 3.
- All dates are relative to the Gregorian calendar. Astropixels.com uses Julian for pre-1582, this is converted to Gregorian for clarity.
var LeapMonthProgression = MonthProgression{ time.January: { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, }, time.February: { 0, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, }, time.March: { 0, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, }, time.April: { 0, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, }, time.May: { 0, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, }, time.June: { 0, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, }, time.July: { 0, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, }, time.August: { 0, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, }, time.September: { 0, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, }, time.October: { 0, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, }, time.November: { 0, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, }, time.December: { 0, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, }, }
LeapMonthProgression holds per month the ordinal of a day, January 1st being 0, December 31st being 365 (365 days in a year, plus February 29th is 366, so ordinal number 365).
var NonLeapMonthProgression = MonthProgression{ time.January: { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, }, time.February: { 0, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, }, time.March: { 0, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, }, time.April: { 0, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, }, time.May: { 0, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, }, time.June: { 0, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, }, time.July: { 0, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, }, time.August: { 0, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, }, time.September: { 0, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, }, time.October: { 0, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, }, time.November: { 0, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, }, time.December: { 0, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, }, }
NonLeapMonthProgression holds per month the ordinal of a day, January 1st being 0, December 31st being 364 (365 days in a year, so ordinal number 364).
var YearProgression = map[Year][2]Ordinal{}/* 2613 elements not displayed */
YearProgression holds the number of days since jdcal.StartProgressionYear. The first int in each entry is for jdcal.Gregorian, the second for jdcal.Julian.
var ZonesTable = [...]ZoneEntry{}/* 114 elements not displayed */
ZonesTable defines matching geographical zones to the date of adoption of the Gregorian calendar. Some zones temporarily reverted to the Julian calendar, these have multiple cutover dates.
This table reflects https://en.wikipedia.org/wiki/List_of_adoption_dates_of_the_Gregorian_calendar_by_country.
Note: The Cutovers entries are the dates where that period STOPPED. So: "{Year: 1918, Month: time.April, Day: 17, Type: Julian}" is the Julian date 1918/04/16, when the Julian calendar was abandoned in favor of "the other one", being the Gregorian.
Another note: All symbols of the table are exported (upper case). You can skip reading the table; rather, have a look at the "Zones*()" functions that can do the lifting.
Functions ¶
This section is empty.
Types ¶
type CalendarYear ¶ added in v0.0.4
CalendarYear wraps a Year with a calendar Type (Julian or Gregorian).
func NewCalendarYear ¶ added in v0.0.12
func NewCalendarYear(y Year, tp Type) (CalendarYear, error)
NewCalendarYear returns a CalendarYear for a given year and calendar type.
func (CalendarYear) DaysPerMonth ¶ added in v0.0.8
func (c CalendarYear) DaysPerMonth() []int
DaysPerMonth returns for each time.Month the number of days, taking into account the calendar type (Julian or Gregorian) and leap years. Example:
cyr, err := NewCalendarYear(1900, jdcal.Julian) if err != nil { ... } dpm := cyr.DaysPerMonth() fmt.Println(dpm[time.February])
func (CalendarYear) HolidayDate ¶ added in v0.0.6
func (cyr CalendarYear) HolidayDate(h Holiday) (Date, error)
HolidayDate returns for a given CalendarYear the Date of one of the Holidays. The type of the returned date matches the type of the calendar year. E.g., if the calendar year is Julian 1370, then the returned date is also on the Julian calendar.
Easter is defined as the next Sunday beyond the ecclesiastical spring equinox of March 21st. If this equinox is a Sunday, then the next one is taken.
Ascension Day is on the 40th day after Easter (so plus 39), making it a Thursday.
Pentecost is on the 50th day after Easter (so plus 49), making it a Sunday.
func (CalendarYear) IsLeap ¶ added in v0.0.4
func (cYear CalendarYear) IsLeap() bool
IsLeap is true when a year indicate that that year should be a leap year for the given calendar type. IsLeap implements the following definition:
https://en.wikipedia.org/wiki/Leap_year:
The historic Julian calendar has three common years of 365 days followed by a leap year of 366 days, by extending February to 29 days rather than the common 28.
The Gregorian calendar, the world's most widely used civil calendar, makes a further adjustment for the small error in the Julian algorithm. Again each leap year has 366 days instead of 365. This extra leap day occurs in each year that is an integer multiple of 4 (except for years evenly divisible by 100, but not by 400).
Example:
var cyr jdcal.CalendarYear cyr = { Year: 1900, Type: jdcal.Julian, } fmt.Println(cyr.IsLeap()) // true cyr.Type = jdcal.Gregorian fmt.Println(cyr.IsLeap()) // false
func (CalendarYear) String ¶ added in v0.0.4
func (c CalendarYear) String() string
String returns the readable representation for a CalendarYear, e.g. "1600 Julian".
type ConversionAlgorithm ¶ added in v0.0.13
type ConversionAlgorithm int
ConversionAlgoritm (an int) represents the applicable conversion algorithm.
const ( ByProgression ConversionAlgorithm // Default conversion algorithm, fast ByLookup // Slow conversion algorithm, but thoroughly tested )
var Algorithm ConversionAlgorithm = ByProgression
func (ConversionAlgorithm) String ¶ added in v0.0.13
func (c ConversionAlgorithm) String() string
type ConversionEntry ¶
type ConversionEntry struct {
JDate, GDate Date
}
ConversionEntry wraps one Julian and one Gregorian date. The ConversionTable is an array of such entries.
type Date ¶
Date wraps a year, month, day and calendar type (Julian or Gregorian); basically a YMD with a type.
func First ¶
First returns the first convertible day for a given type. Dates before this cannot be converted; Convert() would throw an error. This is a limitation of the ConversionTable. Example:
jd := jdcal.First(jdcal.Julian) // First convertible date gd, err := jd.Convert() // err will be nil, jd can be converted
The first convertible dates point to the same day, despite being different day numbers on the Julian or Gregorian calendars.
func Last ¶
Last returns the last convertible date for a given type. Dates after this cannot be converted; Convert() would throw an error. This is a limitation of the ConversionTable. Example:
gd := jdcal.Last(jdcal.Gregorian) // Last convertible date gd = gd.Forward() // Move 1 day forward jd, err := gd.Convert() // err will be set, gd cannot be converted
func NewDate ¶ added in v0.0.12
NewDate is a helper function to construct a Date from a year, month, day and calendar type. The two snippets are equivalent:
d, err := jdcal.New(1962, time.August, 19, jdcal.Gregorian) if err != nil {...} d := Date{Year: 1962, Month: time.August, Day: 19, Type: jdcal.Gregorian} err := d.Valid() if err {...}
func NewDateFromString ¶ added in v0.0.12
NewFromString is a helper function to convert a string in the format "YYYY/MM/DD" into a date of a given Type (Julian or Gregorian). It chaines StringToYMD() and New().
func (Date) Advance ¶
Advance returns a date that is one day later, honoring leap days for Julian or Gregorian calendars. The reference date (receiver) is not modified. Example:
jd0, err := jdcal.Date(1900, time.February, 28, jdcal.Julian) if err != nil {...} jd1 := jd0.Advance() // Copy of jd but a day ahead fmt.Println(jd1) // February 29th gd, err := jdcal.Date(1900, time.February, 28, jdcal.Gregorian) if err != nil {...} gd = gd.Advance() // advance gd itself fmt.Println(gd) // March 1st
func (Date) After ¶
After is true when the date in question occurs later than the other date. Note that different date types raise an error. When comparing different date types, the caller must first convert:
jd, err := jdcal.New(1666, time.March, 13, jdcal.Julian) // a Julian date in 1666 if err != nil {...} gd, err := jdcal.New(2023, time.December, 4, jdcal.Gregorian) // a Gregorian date in 2023 if err != nil {...} gdTmp, err := jd.Convert() // jd as a Gregorian date if err != nil {...} fmt.Println(gd.After(gdTmp)) // true; the 2023 date comes after the 1666 date
func (Date) AfterOrEqual ¶ added in v0.0.1
AfterOrEqual is true when the date in question occurs later than the other date. Comparing dates of different types raises an error, see Equal().
func (Date) AsTime ¶ added in v0.0.2
AsTime returns the jdcal.Date as a time.Time type, so that one can apply all standard functions of https://pkg.golang.ir/time#Time. The time coordinates are pinned at noon, UTC.
The date type (jdcal.Julian or jdcal.Gregorian) does not matter; the date is converted if needed (time.Time is, by definition, Gregorian).
func (Date) Backward ¶ added in v0.0.8
Backward returns a date that is one day before, hononing leap years for Julian or Gregorian calendars. The reference date (receiver) is not modified. Example:
jd0, err := jdcal.Date(1900, time.March, 1, jdcal.Julian) if err != nil {...} jd1 := jd0.Backward() // Copy of jd but a day before fmt.Println(jd1) // February 29th gd, err := jdcal.Date(1900, time.March, 1, jdcal.Gregorian) if err != nil {...} gd = gd.Backward() // Decrease gd itself fmt.Println(gd) // February 28th
func (Date) Before ¶
Before is true when the date in question occurs earlier than the other date. Note that different date types raise an error, see After().
func (Date) BeforeOrEqual ¶ added in v0.0.1
BeforeOrEqual is true when the date in question occurs earlier than the other date or exactly on that other date. Note that different date types raise an error, see After().
func (Date) Convert ¶
Convert converts a jdcal.Date to the "other" format: from Julian to Gregorian, or vv. Example:
jd, err := jdcal.New(1712, time.February, 19, jdcal.Julian) if err != nil {...} gd, err := jd.Convert() if err != nil {...} fmt.Println(gd) // Gregorian 1712/03/01
func (Date) Equal ¶
Equal is true when two dates point to the same day. Different date types cannot be compared, see After().
func (Date) Forward ¶ added in v0.0.8
Forward returns a date that is one day later, honoring leap days for Julian or Gregorian calendars. The reference date (receiver) is not modified. Example:
jd0, err := jdcal.Date(1900, time.February, 28, jdcal.Julian) if err != nil {...} jd1 := jd0.Forward() // Copy of jd but a day ahead fmt.Println(jd1) // February 29th gd, err := jdcal.Date(1900, time.February, 28, jdcal.Gregorian) if err != nil {...} gd = gd.Forward() // Advance gd itself fmt.Println(gd) // March 1st
func (Date) InZone ¶ added in v0.0.1
InZone returns true when the date in question matches in the calendar progression as defined by the ZoneEntry. For example, assuming that the ZoneEntry is:
{ Name: "Netherlands (Groningen City)", Cutovers: []Date{ {Year: -500, Month: time.February, Day: 28, Type: Gregorian} // started using Julian {Year: 1583, Month: time.January, Day: 1, Type: Julian}, // switched to Gregorian {Year: 1594, Month: time.November, Day: 10, Type: Gregorian}, // switched to Julian {Year: 1700, Month: time.December, Day: 31, Type: Julian}, // switched to Gregorian }, }
Stated differently, the zone is defined as follows:
The zone calendar started on Gregorian -500/02/28, the next day was Julian date Julian 1583/01/01 became Gregorian 1583/01/11, the next day was a Gregorian date Gregorian 1594/11/10 became Julian 1594/10/31, the next day was a Julian date Julian 1700/12/31 became Gregorian 1701/01/11, the next day was a Gregorian date
Regarding which dates are possible in the zone, the following applies:
1580/01/01 occurs in the zone as a Julian date, but not as as a Gregorian 1590/01/01 occurs in the zone as a Gregorian date, but not as a Julian 1600/01/01 occurs in the zone as a Julian date, but not as a Gregorian 1800/01/01 occurs in the zone as a Gregorian date, but not as a Julian
Example:
jd, err := jdcal.New(1580, 1, 1, jdcal.Julian) if err != nil { ... } in, err := jd.InZone(zoneEntry) // obtained using jdcal.ZonesByname("Groningen City") if err != nil { ... } fmt.Println(in) // true gd, err := jdcal.New(1580, 1, 1, jdcal.Gregorian) if err != nil { ... } in, err := gd.InZone(zoneEntry) if err != nil { ... } fmt.Println(in) // false
Just around the cutover dates, the following applies. Around the cutover from Gregorian 1594/11/10 to Julian 1594/10/31:
- 1594/11/09 can be both a Gregorian and a Julian date. Gregorian, because it's one day before the switch over. But it can also be a Julian date, when it points 9 days beyond this switch over.
- 1594/11/10 can be both a Julian and a Gregorian date. Gregorian, because it's the switch over date. Julian, because it points 10 days beyond the switch over.
- 1594/11/11 can only be a Julian date; it doesn't exist in the Gregorian calendar in this zone, but points to the Julian calendar 11 days beyond the switch over.
Around the cutover from Julian 1700/12/31 to Gregorian Gregorian 1701/01/11, the following applies:
- 1700/12/30 and 1700/12/31 must be a Julian dates, there is no Gregorian representation. Gregorian 1700/12/30 would mean Julian 1700/12/19, and that's before the cutover.
- 1701/01/01 can't be either, it's a lost date. In the zone, the Julian calendar ends on 1700/12/31 but the Gregorian only starts on 1594/10/31.
func (Date) IsSet ¶ added in v0.0.1
IsSet returns true when any of the fields Year, Month or Day of a given date have a non-zero value. IsSet is false when a date is not initialized. Example:
d := Date{} fmt.Println(d.IsSet()) // false d.Day = 1 fmt.Println(d.IsSet()) // true
func (Date) Ordinal ¶ added in v0.0.11
Ordinal returns the ordinal day for a given date. This is a daycount since "start of epoch", liberally defined as the constant StartProgressionYear. This is the reverse of OrdinalToDate.
func (Date) String ¶
String returns a printable version of a date in the format "TYPE YYYY/MM/DD", e.g. "Julian 1234/12/27". The year may be prefixed by a - to indicate negative values.
func (Date) Valid ¶
Valid returns an error when a date cannot be processed. The date must not exceed the maximum number of month days (e.g., April 31st is wrong, February 29th may only occur in leap years) and Convert() must be able to process it: it can't be outside of the range [Date.First() .. Date.Last()].
func (Date) Weekday ¶ added in v0.0.1
Weekday returns the day of the week (time.Sunday, time.Monday etc.) for the given date. The date type (jdcal.Julian or jdcal.Gregorian) doesn't matter; if needed, the date is converted before determining the weekday.
The following two snippets are equivalent:
dt, err := jdcal.New(...) if err != nil { ... } // Alternative 1 wd, err := dt.Weekday() if err != nil { ... } // Alternative 2 tm, err := dt.AsTime() if err != nil { ... } wd := tm.Weekday()
type Holiday ¶ added in v0.0.4
type Holiday int
Holiday enumarates yearly holidays.
const ( AshWednesday Holiday GoodFriday Easter Ascension Pentecost )
type MD ¶ added in v0.0.10
MD is a representation of a month and a day; basically a YMD without a year.
type MonthProgression ¶ added in v0.0.11
MonthProgression maps arrays of ordinals to months. There is such a table for leap years (LeapMonthProgression) and for non-leap years (NonLeapMonthProgression).
type Ordinal ¶ added in v0.0.11
type Ordinal int
Ordinal (an int) represents the day number since epoch start.
type Type ¶
type Type int
Type (an int) defines the calendar type for a jdcal.Date or a jdcal.CalendarYear: jdcal.Gregorian or jdcal.Julian.
type YMD ¶ added in v0.0.10
YMD is a representation of a year, month and a day; basically a Date without a type.
func StringToYMD ¶ added in v0.0.1
StringToYMD is a simple string parser to convert a date in the format "YYYY/MM/DD" to a separate year, month and day. The separator is a slash, to allow for easier negative years (as in "-25/02/28"). An error occurs when the parts in the argument cannot be converted; the validity of the date is not checked (so "2020/12/100" would pass).
type Year ¶ added in v0.0.4
type Year int
Year is an integer and the receiver type for some helper functions.
type ZoneEntry ¶ added in v0.0.1
type ZoneEntry struct { Name string // Zone name, e.g. "Denmark" Cutovers []Date // List of dates when the zone switched from a given calendar }
ZoneEntry wraps a zone name with the dates where that zone switched to the Gregorian calendar, possibly later back to the Gregorian, etc. The ZoneTable is an array of such entries.
The CutOvers list is an array of Dates where this zone switched FROM a calendar TO another one. E.g., when CutOvers is:
Cutovers: []Date{ // -500 to 1584: Julian calendar applies // 1584 to 1597: Switched to Gregorian // 1597 to 1798: Switched back to Julian // 1798 to now: Ended up with Gregorian {Year: -500, Month: time.February, Day: 28, Type: Gregorian}, {Year: 1584, Month: time.January, Day: 1, Type: Julian}, {Year: 1597, Month: time.January, Day: 1, Type: Gregorian}, {Year: 1798, Month: time.December, Day: 25, Type: Julian}, }
Then that means:
- The calendar for this zone starts at -500/02/28 Gregorian (or: -500 March 1st Julian, convert yourself if you think that is handy). On that day the zone stopped using the Gregorian, and started using the Julian calendar.
- On 1584/01/01 Julian, the zone switched to Gregorian ("the other one").
- On 1597/01/01 Gregorian, the zone switched to Julian. So they switched back.
- Finally, on 1798/12/25, they switched again. To Gregorian.
func SingleZone ¶ added in v0.0.9
SingleZone returns a ZoneEntry matching a name, or an error when nothing matches, or when multiple zones match.
Example:
var zn jdcal.ZoneEntry var err error zn, err = jdcal.SingleZone("netherlands") // error: >1 matches zn, err = jdcal.SingleZone("gelderland") // nil error, zn is valid zn, err = jdcal.SingleZone("xyzzy") // error: 0 matches
func ZonesByName ¶ added in v0.0.1
ZonesByname returns a list of ZoneEntry's matching the input argument. The matching is done without regard to case. E.g., ZonesByName("netherlands") will return zones for "Belgium (Southern Netherlands)", "Netherlands (Brabant)" and ~7 more.
Example:
fmt.Println(jdcal.ZonesByName("netherlands")) // Output: // Belgium (Southern Netherlands) // Started using the Julian calendar on Gregorian -0500/02/28 // Switched to the Gregorian calendar on Julian 1582/12/20 // Netherlands (Brabant) // Started using the Julian calendar on Gregorian -0500/02/28 // Switched to the Gregorian calendar on Julian 1582/12/14 // Netherlands (Drenthe) // Started using the Julian calendar on Gregorian -0500/02/28 // Switched to the Gregorian calendar on Julian 1701/04/30 // Netherlands (Frisia) // Started using the Julian calendar on Gregorian -0500/02/28 // Switched to the Gregorian calendar on Julian 1701/12/31 // Netherlands (Gelderland) // Started using the Julian calendar on Gregorian -0500/02/28 // Switched to the Gregorian calendar on Julian 1700/06/12 // Netherlands (Groningen City) // Started using the Julian calendar on Gregorian -0500/02/28 // Switched to the Gregorian calendar on Julian 1583/01/01 // Switched to the Julian calendar on Gregorian 1594/11/10 // Switched to the Gregorian calendar on Julian 1700/12/31 // Netherlands (Holland) // Started using the Julian calendar on Gregorian -0500/02/28 // Switched to the Gregorian calendar on Julian 1583/01/01 // Netherlands (Utrecht, Overijssel) // Started using the Julian calendar on Gregorian -0500/02/28 // Switched to the Gregorian calendar on Julian 1700/11/30 // Netherlands (Zeeland, States General) // Started using the Julian calendar on Gregorian -0500/02/28 // Switched to the Gregorian calendar on Julian 1582/12/14
func (ZoneEntry) String ¶ added in v0.0.1
String returns a human-readable representation of a ZoneEntry. The returned string is not usable for machine parsing, it is only meant for human consumption. Example:
Switzerland (Appenzell Ausserrhoden) Started using the Julian calendar on Gregorian -0500/02/28 Switched to the Gregorian calendar on Julian 1584/01/01 Switched to the Julian calendar on Gregorian 1597/01/01 Switched to the Gregorian calendar on Julian 1798/12/25
The first line is the start of the calendar. This will in most cases be the "start of time recording", except e.g., China where before any supported calendar was used, dates would be in a not-supported format. China will have "Started using the Gregorian calendar on ..." and nothing else:
China Started using the Gregorian calendar on Julian 1911/12/01
Next entries, when present, are switches. In the example of Switzerland (Appenzell Ausserrhoden):
- The zone switched to the Gregorian calendar on 1584/01/01 (which must be a Julian date, because they were switching).
- Then they switched back to Julian on 1597/01/01 (on the Gregorian calendar, because they were switching).
- Etc..
Source Files ¶
- algorithm.go
- calendaryear_dayspermonth.go
- calendaryear_holiday_date.go
- calendaryear_isleap.go
- calendaryear_new.go
- calendaryear_string.go
- date_advance.go
- date_after.go
- date_after_equal.go
- date_astime.go
- date_backward.go
- date_before.go
- date_before_equal.go
- date_convert.go
- date_equal.go
- date_first.go
- date_forward.go
- date_inzone.go
- date_isset.go
- date_last.go
- date_new.go
- date_ordinal.go
- date_string.go
- date_table.go
- date_valid.go
- date_weekday.go
- doc.go
- fullmoons.go
- holiday_string.go
- md_string.go
- ordinal.go
- progressiontable.go
- singlezone.go
- type_other.go
- type_string.go
- types.go
- util.go
- year_string.go
- year_valid.go
- ymd_string.go
- zone_entry_string.go
- zones_by_name.go
- zones_table.go
Directories ¶
Path | Synopsis |
---|---|
main
|
|
demo1
main/demo1/demo1.go
|
main/demo1/demo1.go |
demo2
main/demo2/demo2.go
|
main/demo2/demo2.go |
demo3
main/demo3/demo3.go
|
main/demo3/demo3.go |
demo4
main/demo4/demo4.go
|
main/demo4/demo4.go |
demo5
main/demo5/demo5.go
|
main/demo5/demo5.go |
demo6
main/demo6/demo6.go
|
main/demo6/demo6.go |
demo7
main/demo7/demo7.go
|
main/demo7/demo7.go |