Hebrew
NAME
Date::Calendar::Hebrew - Conversions from / to the Hebrew calendar
SYNOPSIS
Converting a Gregorian date (e.g. 16th June 2019) into Hebrew
use Date::Calendar::Hebrew;
my Date $TPC2019-Pittsburgh-grg;
my Date::Calendar::Hebrew $TPC2019-Pittsburgh-heb;
$TPC2019-Pittsburgh-grg .= new(2019, 6, 16);
$TPC2019-Pittsburgh-heb .= new-from-date($TPC2019-Pittsburgh-grg);
say $TPC2019-Pittsburgh-heb;
# --> 5779-03-13
say "{.day-name} {.day} {.month-name} {.year}" with $TPC2019-Pittsburgh-heb;
# --> Yom Rishon 13 Sivan 5779
say $TPC2019-Pittsburgh-heb.strftime("%A %d %B %Y");
# --> Yom Rishon 13 Sivan 5779
Converting an Hebrew date (e.g. 6 Av 5779) into Gregorian
use Date::Calendar::Hebrew;
my Date::Calendar::Hebrew $Perlcon-Riga-heb;
my Date $Perlcon-Riga-grg;
$Perlcon-Riga-heb .= new(year => 5779
, month => 5
, day => 6);
$Perlcon-Riga-grg = $Perlcon-Riga-heb.to-date;
say $Perlcon-Riga-grg;
# --> '2019-08-07'
Hannukah begins on 25 Kislev at sunset. What is the corresponding Gregorian date?
use Date::Calendar::Hebrew;
use Date::Calendar::Strftime;
my Date::Calendar::Hebrew $hannukah-heb;
my Date $hannukah-grg;
$hannukah-heb .= new(year => 5785
, month => 9
, day => 25
, daypart => after-sunset());
$hannukah-grg = $hannukah-heb.to-date;
say $hannukah-grg;
# --> '2024-12-25' instead of '2024-12-26'
# on the other hand:
$hannukah-heb .= new(year => 5785, month => 9, day => 25, daypart => before-sunrise());
$hannukah-grg = $hannukah-heb.to-date;
say $hannukah-grg;
# --> '2024-12-26'
$hannukah-heb .= new(year => 5785, month => 9, day => 25, daypart => daylight());
$hannukah-grg = $hannukah-heb.to-date;
say $hannukah-grg;
# --> '2024-12-26' also
DESCRIPTION
Date::Calendar::Hebrew is a class representing dates in the Hebrew calendar. It allows you to convert an Hebrew date into Gregorian (or possibly other) calendar and the other way.
The Hebrew calendar is a luni-solar calendar. Some months are 29-day long, other are 30-day long and still other varies between 29 and 30 from a year to the other, so on average, the duration of a month is very close to the duration of a lunation. The years have 12 or 13 months, so while the duration of the Hebrew year oscillates between 353 and 385 days, on average it is very close to the duration of the tropic year.
The switch from a date to the next occurs at sunset. This point has
been implemented in this module, by adding a daypart parameter. So,
while 16th June 2019 during daylight converts to 13 Sivan 5779, 16th
June 2019 after sunset converts to 14 Sivan 5779.
Note: in the direction Gregorian β Hebrew, this requires the use of
Date::Calendar::Gregorian:api<1>, the core module Date does not
work.
A peculiar characteristic of this calendar is that the switch from a year to the next occurs when switching from month 6 to month 7. So we have the following:
2019-04-05 5779-13-29 Yom Shishi 29 Adar II 5779
2019-04-06 5779-01-01 Yom Shabbat 1 Nisan 5779 --> no change of year
...
2019-09-29 5779-06-29 Yom Rishon 29 Elul 5779
2019-09-30 5780-07-01 Yom Sheni 1 Tishrey 5780 --> new year
METHODS
Constructors
new
Create an Hebrew date by giving the year, month and day numbers, plus
the day part (before-sunrise, daylight or after-sunset).
new-from-date
Build an Hebrew date by cloning an object from another class. This
other class can be the core class Date or any
Date::Calendar::xxx class with a daycount method and,
hopefully, a daypart method.
new-from-daycount
Build an Hebrew date from the Modified Julian Day number and the
daypart value.
Accessors
gist
Gives a short string representing the date, in YYYY-MM-DD format.
year, month, day
The numbers defining the date.
daycount
The MJD (Modified Julian Date) number for the date.
daypart
A number indicating which part of the day. This number should be filled and compared with the following subroutines, with self-documenting names:
before-sunrise()
daylight()
after-sunset()
month-name
The month of the date, as a string.
month-abbr
The month of the date, as a 3-char string.
This is always a 3-char string, even for month "Av". The reason is that the abbreviations are often used in tables and arrays so that, when typeset with a constant-width font, it keeps the vertical alignment of the table elements. Therefore, the abbreviation is 3-char for all months.
day-name
The name of the day within the week.
day-of-week
The number of the day within the week (1 for Sunday / Yom Rishon, 7 for Saturday / Yom Shabbat).
week-number
The number of the week within the year, 1 to 50 or 1 to 51 on normal years, 1 to 54 or 1 to 55 on leap years. Similar to the "ISO date" as defined for Gregorian date. Week number 1 is the SunβSat span that contains the first Wednesday / Yom Revi'i of the year, week number 2 is the SunβSat span that contains the second Wednesday / Yom Revi'i of the year and so on.
week-year
Mostly similar to the year attribute. Yet, the last days of the
year and the first days of the following year can be sort-of
transferred to the other year. The week-year attribute reflects
this transfer. While the real year always begins on 1st Tishrey and
ends on the 29th Elul, the week-year always begins on Sunday / Yom
Rishon and it always ends on Saturday / Yom Shabbat.
day-of-year
How many days since the beginning of the year. 1 to 353 (or 354 or 355) on normal years, 1 to 383 (or 384 or 385) on leap years.
Other Methods
to-date
Clones the date into a core class Date object or some
Date::Calendar::xxx compatible calendar class. The target class
name is given as a positional parameter. This parameter is optional,
the default value is "Date" for the Gregorian calendar.
To convert a date from a calendar to another, you have two conversion styles, a "push" conversion and a "pull" conversion. For example, while converting "26 Tamuz 5779" to the French Revolutionary calendar, you can code:
use Date::Calendar::Hebrew;
use Date::Calendar::FrenchRevolutionary;
my Date::Calendar::Hebrew $d-orig;
my Date::Calendar::FrenchRevolutionary $d-dest-push;
my Date::Calendar::FrenchRevolutionary $d-dest-pull;
$d-orig .= new(year => 5779
, month => 4
, day => 26);
$d-dest-push = $d-orig.to-date("Date::Calendar::FrenchRevolutionary");
$d-dest-pull .= new-from-date($d-orig);
When converting from the core class Date, use the pull style.
When converting to the core class Date, use the push style. When
converting from any class other than the core class Date to any
other class other than the core class Date, use the style you
prefer. For the Gregorian calendar, instead of the core class Date,
you can use the child class Date::Calendar::Gregorian which allows
both push and pull styles.
strftime
This method is very similar to the homonymous functions you can find
in several languages (C, shell, etc). It also takes some ideas from
printf-similar functions. For example
$df.strftime("%04d blah blah blah %-25B")
will give the day number padded on the left with 2 or 3 zeroes to
produce a 4-digit substring, plus the substring " blah blah blah ",
plus the month name, padded on the right with enough spaces to produce
a 25-char substring. Thus, the whole string will be at least 42 chars
long. By the way, you can drop the "at least" mention, because the
longest month name is 7-char long, so the padding will always occur
and will always include at least 18 spaces.
A strftime specifier consists of:
A percent sign,
An optional minus sign, to indicate on which side the padding occurs. If the minus sign is present, the value is aligned to the left and the padding spaces are added to the right. If it is not there, the value is aligned to the right and the padding chars (spaces or zeroes) are added to the left.
An optional zero digit, to choose the padding char for right-aligned values. If the zero char is present, padding is done with zeroes. Else, it is done wih spaces.
An optional length, which specifies the minimum length of the result substring.
An optional
"E"or"O"modifier. On some older UNIX system, these were used to give the extended or localized version of the date attribute. Here, they rather give alternate variants of the date attribute. Not used with the Hebrew calendar.A mandatory type code.
The allowed type codes are:
- %A
The full day of week name.
- %b
The abbreviated month name.
- %B
The full month name.
- %d
The day of the month as a decimal number (range 01 to 30).
- %e
Like %d, the day of the month as a decimal number, but a leading
zero is replaced by a space.
- %f
The month as a decimal number (1 to 13). Unlike %m, a leading zero
is replaced by a space.
- %F
Equivalent to %Y-%m-%d (the ISO 8601 date format)
- %G
The "week year" as a decimal number. Mostly similar to %Y, but it
may differ on the very first days of the year or on the very last
days. Analogous to the year number in the so-called "ISO date" format
for Gregorian dates.
- %j
The day of the year as a decimal number (range 001 to 385).
- %L
Redundant with %Y and deprecated: the year number.
- %m
The month as a two-digit decimal number (range 01 to 13), including a leading zero if necessary.
- %n
A newline character.
- %Ep
Gives a 1-char string representing the day part:
βΎorU+263Ebefore sunrise,βΌorU+263Cduring daylight,β½orU+263Dafter sunset.
Rationale: in C or in other programming languages, when strftime
deals with a date-time object, the day is split into two parts, before
noon and after noon. The %p specifier reflects this by giving a
"AM" or "PM" string.
The 3-part splitting in the Date::Calendar::xxx may be
considered as an alternate splitting of a day. To reflect this in
strftime, we use an alternate version of %p, therefore %Ep.
- %t
A tab character.
- %u
The day of week as a 1..7 number.
- %V
The week number as defined above, similar to the week number in the so-called "ISO date" format for Gregorian dates.
- %Y
The year as a decimal number.
- %%
A literal `%' character.
PROBLEMS AND KNOWN ISSUES
I have found no source for day abbreviations, so only the months are abbreviated.
Security issues
Another issue, as explained in the Date::Calendar::Strftime
documentation. Please ensure that format-string passed to strftime
comes from a trusted source. Failing that, the untrusted source can
include a outrageous length in a strftime specifier and can drain
your PC's RAM very fast.
Relations with :ver<0.0.x> classes and with core class Date
Version 0.1.0 (and API 1) was introduced to ease the conversions with
other calendars in which the day is defined as midnight-to-midnight.
If all Date::Calendar::xxx classes use version 0.1.x and API 1,
the conversions will be correct. But if some Date::Calendar::xxx
classes use version 0.0.x and API 0, there might be problems.
A date from a 0.0.x class has no daypart attribute. But when "seen"
from a 0.1.x class, the 0.0.x date seems to have a daypart
attribute equal to daylight. When converted from a 0.1.x class to a
0.0.x class, the date may just shift from after-sunset (or
before-sunrise) to daylight, or it may shift to the daylight
part of the prior (or next) date. This means that a roundtrip with
cascade conversions may give the starting date, or it may give the
date prior or after the starting date.
If you install <Date::Calendar::Hebrew:ver<0.1.0>>, why would you
refrain from upgrading other Date::Calendar::xxxx classes? So
actually, this issue applies mainly to the core class Date, because
you may prefer avoiding the installation of
Date::Calendar::Gregorian.
Time
This module and the Date::Calendar::xxx associated modules are
still date modules, they are not date-time modules. The user has to
give the daypart attribute as a value among before-sunrise,
daylight or after-sunset. There is no provision to give a HHMMSS
time and convert it to a daypart parameter.
SEE ALSO
Raku Software
Date::Calendar::Strftime or https://github.com/jforget/raku-Date-Calendar-Strftime
Date::Calendar::Gregorian or https://github.com/jforget/raku-Date-Calendar-Gregorian
Date::Calendar::Julian or https://github.com/jforget/raku-Date-Calendar-Julian
Date::Calendar::CopticEthiopic or https://github.com/jforget/raku-Date-Calendar-CopticEthiopic
Date::Calendar::MayaAztec or https://github.com/jforget/raku-Date-Calendar-MayaAztec
Date::Calendar::FrenchRevolutionary or https://github.com/jforget/raku-Date-Calendar-FrenchRevolutionary
Date::Calendar::Hijri or https://github.com/jforget/raku-Date-Calendar-Hijri
Date::Calendar::Persian or https://github.com/jforget/raku-Date-Calendar-Persian
Date::Calendar::Bahai or https://github.com/jforget/raku-Date-Calendar-Bahai
Perl 5 Software
Date::Converter which I used as a model for the computations in this module.
DateTime::Event::Jewish::Sunrise
Other Software
date(1), strftime(3)
calendar/cal-hebrew.el in emacs.2 or xemacs.
CALENDRICA 4.0 -- Common Lisp, which can be download in the "Resources" section of https://www.cambridge.org/us/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition?format=PB&isbn=9781107683167 (Actually, I have used the 3.0 version which is not longer available)
Books
Calendrical Calculations (Third or Fourth Edition) by Nachum Dershowitz and Edward M. Reingold, Cambridge University Press, see http://www.calendarists.com or https://www.cambridge.org/us/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition?format=PB&isbn=9781107683167.
AUTHOR
Jean Forget <J2N-FORGET at orange dot fr>
THANKS
Many thanks to all those who were involved in Perl 6 / Raku, Rakudo and Rakudo-Star.
Many thanks to Andrew, Laurent and brian for writing books that
helped me learn Perl 6 / Raku.
And some additional thanks to Andrew, whose Date::Converter module
was the basis of the computations in this module.
COPYRIGHT AND LICENSE
Copyright (c) 2019, 2020, 2023, 2024 Jean Forget, all rights reserved
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.