Bahai

NAME

DESCRIPTION

Date::Calendar::Bahai - Conversions from / to the Baháʼí calendar

SYNOPSIS

Converting a Gregorian date (e.g. 17th May 2021) into Baháʼí


use Date::Calendar::Bahai;
my Date $dt-greg;
my Date::Calendar::Bahai $dt-bahai;

$dt-greg    .= new(2021, 5, 17);
$dt-bahai .= new-from-date($dt-greg);

say $dt-bahai;
# --> 0178-04-01
say $dt-bahai.strftime("%A %e %B %Y");
# --> Kamál 1 ‘Aẓamat 178

Converting a Bahai date (e.g. 19 Jamál 178) into Gregorian

use Date::Calendar::Bahai;
my  Date::Calendar::Bahai $dt-bahai;
my  Date $dt-greg;

$dt-bahai .= new(year => 178, month => 3, day => 19);
$dt-greg   = $dt-bahai.to-date;

say $dt-greg;
# --> 2021-05-16

Converting a date while caring about sunset:


use Date::Calendar::Strftime;
use Date::Calendar::Bahai;

my Date::Calendar::Bahai $dt-bahai;
my Date                  $dt-greg;

$dt-bahai .= new(year => 181, month => 13, day => 11, daypart => after-sunset());
$dt-greg   = $dt-bahai.to-date;
say $dt-greg.gist;   # --> 2024-11-13

# on the other hand
$dt-bahai .= new(year => 181, month => 13, day => 11, daypart => before-sunrise());
$dt-greg   = $dt-bahai.to-date;
say $dt-greg.gist;   # --> 2024-11-14

$dt-bahai .= new(year => 181, month => 13, day => 11, daypart => daylight());
$dt-greg   = $dt-bahai.to-date;
say $dt-greg.gist;   # --> 2024-11-14

DESCRIPTION

Date::Calendar::Bahai is a class representing dates in the initial Baháʼí calendar, before the 2015 reform. It allows you to convert a Baháʼí date into Gregorian or into other implemented calendars, and it allows you to convert dates from Gregorian or from other calendars into Baháʼí.

In the Baháʼí calendar, days begin at sunset. When converting from / to calendar with midnight-to-midnight days, be sure to add the proper daypart build parameter to get the proper converted date.

The years are numbered in two different ways: the usual sequential count in base 10, and a set of three embedded 19-year cycles, each cycle being numbered 1 to 19. For example, the year beginning in March 2021 and ending in March 2022 is both year 178 BE (Baháʼí Era) and year 7 of cycle 10 of major cycle 1. Within the 19-year cycle, years are named, so year 178 can also be year Abad of cycle 10 of major cycle 1 or year Abad of 10th Váḥid of 1st Kull-i-Shay’a.

Years are divided in 19 months of 19 days each, plus a period of 4 or 5 additional days. These additional days are not at the end of the year, but before the last month of the year. Therefore, in this class, months are numbered 1 to 18 and then 20, while the additional days are considered as a small month numbered 19. The reason for this counterintuitive setup might be that before 2015, the Baháʼí calendar was precisely synchronised with the Gregorian calendar and that the new year (Naw-Rūz) was always on 21st of March. By putting the additional days before the last month, the additional days would span from 26th February until 1st March, both in normal and leap years, and the last month would span from 2nd March until 20th March, both in normal and leap years.

The distribution provides also the Date::Calendar::Bahai::Astronomical class which gives the version of the Baháʼí calendar as defined by the 2015 reform.

The calendar implemented by the arithmetic module is not limited to dates in the Gregorian range 1844--2015. It allows you to convert dates after the 2015 reform while pretending the reform did not happen and that the Baháʼí calendar is still synchronised with the Gregorian calendar.

METHODS

Constructors

new

Create an Baháʼí date by giving the year, month and day numbers and the locale code, plus optionally the day part (before-sunrise, daylight or after-sunset).

The year can be specified either by a single parameter year, or by three parameters cycle-year, cycle and major-cycle.

Currently implemented locales are ar for Arabic (default locale), en for English and fr for French.

use Date::Calendar::Strftime;
use Date::Calendar::Bahai;
my  Date::Calendar::Bahai $dt-bahai;
$dt-bahai .= new(year => 178, month => 3, day => 19);
$dt-bahai .= new(major-cycle => 1, cycle => 10, cycle-year => 7, month => 3, day => 19);
$dt-bahai .= new(year => 178, month => 3, day => 19, daypart => after-sunset(), locale => 'fr');

new-from-date

Build an Baháʼí 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 Baháʼí 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.

major-cycle, cycle, cycle-year

The alternate definition of the year.

For strftime, see the specifiers %K, %k and %y.

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()

For strftime, see the specifier %Ep.

month-name

The month of the date, as a string.

month-abbr

The month of the date, as a 3-char string.

day-name

The name of the day within the week.

day-abbr

The weekday of the date, as a 3-char string.

cycle-year-name

The name associated to the year within the 19-year cycle.

daycount

The Modified Julian Day Number (a day-only scheme based on 17 November 1858).

day-of-week

The number of the day within the week (1 for Saturday / Jalál, 7 for Friday / Istiqlál).

week-number

The number of the week within the year, 1 to 52 or 1 to 53. Similar to the "ISO date" as defined for Gregorian date. Week number 1 is the Sat→Fri span that contains the first Tuesday / Fiḍál of the year, week number 2 is the Sat→Fri span that contains the second Tuesday / Fiḍál 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 Bahá and ends on the 19th Alá, the week-year always begins on Saturday / Jalál and it always ends on Friday / Istiqlál.

day-of-year

How many days since the beginning of the year. 1 to 365 on normal years, 1 to 366 on leap years.

is-leap

Returns True if the invocant date belongs to a leap year, False if the invocant date belongs to a normal year.

This method allows an optional parameter, to specify a Baháʼí year (the single-number version). If this parameter is supplied, and the parameter year is tested for leapness and the invocant date is ignored.

use Date::Calendar::Bahai;
my  Date::Calendar::Bahai $dt-bahai;

$dt-bahai .= new(year => 178, month => 3, day => 19);

if $dt-bahai.is-leap {
  say $dt-bahai.year, " is a leap year";
}
if $dt-bahai.is-leap(180) {
  say "180 is a leap year";
}

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 "Istijlál 4 ‘Aẓamat 178" to the French Revolutionary calendar, you can code:


use Date::Calendar::Bahai;
use Date::Calendar::FrenchRevolutionary;

my  Date::Calendar::Bahai               $d-orig;
my  Date::Calendar::FrenchRevolutionary $d-dest-push;
my  Date::Calendar::FrenchRevolutionary $d-dest-pull;

$d-orig .= new(year  => 178
             , month =>   4
             , day   =>   4);
$d-dest-push  = $d-orig.to-date("Date::Calendar::FrenchRevolutionary");
$d-dest-pull .= new-from-date($d-orig);
say $d-orig, ' ', $d-dest-push, ' ', $d-dest-pull;
# --> "178-04-04 0229-09-01 0229-09-01"

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


$dt.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 10-char long, so the padding will always occur and will always include at least 15 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.

  • A mandatory type code.

The allowed type codes are:

%a

The abbreviated day of week.

%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 19).

%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 20). 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 366).

%k

The cycle as a decimal number (range 1 to 19).

%K

The major cycle as a decimal number.

%m

The month as a two-digit decimal number (range 01 to 20), including a leading zero if necessary.

%n

A newline character.

%Ep

Gives a 1-char string representing the day part:

  • ☾ or U+263E before sunrise,

  • ☼ or U+263C during daylight,

  • ☽ or U+263D after 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.

%y

The cycle-year as a decimal number.

On other systems and other languages, the %y specifier is used for the stupid and dangerous action of truncating the year number, which paved the way for the Y2K bug. With the principle of least surprise, this specifier is used here to give the short variant of the year, that is, the 1-to-19 cycle-year. Unlike the other calendars, the use of a short variant here is a legitimate one.

See also %k and %K.

%Ey

The name of the cycle-year.

%%

A literal `%' character.

BUGS AND ISSUES

Although there are 19 real months, the months are numbered until 20 because the additional days (Ayyám-i-Há) are considered as a short pseudo-month numbered 19, so month Alá is numbered 20. This numbering scheme allows easy sorting of dates with the YYYY-MM-DD format. On the other hand, it is incompatible with some other programs' numbering scheme, notably calendar.l by Reingold and Dershowitz.

Is the major cycle limited to the 1..19 range or is it open-ended? Do we need a super-major cycle for the time when the major-cycle reach 19? We'll need to settle on this around Gregorian year 8700, so there is still time...

The astronomical version is defined until year 221, that is Gregorian year 2065. Beyond that, the Date::Calendar::Bahai::Astronomical class silently reverts to the arithmetic version.

Some months has the same name as week days. Be careful and do not mix them.

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 this will 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::Bahai: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::Hebrew or https://github.com/jforget/raku-Date-Calendar-Hebrew

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::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

Perl 5 Software

Date::Converter

Date::Bahai::Simple

Other Software

date(1), strftime(3)

calendar/cal-bahai.el in emacs or xemacs.

CALENDRICA 4.0 -- Common Lisp, which can be downloaded 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

Book

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.

Internet

https://bahai-library.com/uhj_badi_calendar_2014

https://www.badi-calendar.com/faq.php

https://www.funaba.org/cc (website no longer works).

https://en.wikipedia.org/wiki/Bah%C3%A1%27%C3%AD_calendar

https://icalendrier.fr/calendriers-saga/calendriers/baha-i (in French)

AUTHOR

Jean Forget <J2N-FORGET at orange dot fr>

COPYRIGHT AND LICENSE

Copyright (c) 2021, 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.

Date::Calendar::Bahai v0.1.0

Conversions from / to the Baháʼí calendar

Authors

  • Jean Forget

License

Artistic-2.0

Dependencies

Date::Calendar::Strftime

Test Dependencies

Provides

  • Date::Calendar::Bahai
  • Date::Calendar::Bahai::Astronomical
  • Date::Calendar::Bahai::Common
  • Date::Calendar::Bahai::Names

The Camelia image is copyright 2009 by Larry Wall. "Raku" is a trademark of the Yet Another Society. All rights reserved.

Built with Podlite — the markup and publishing tools behind this site.