nepdate 1.0.0.rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6c86b1e5b783d2dc84cc9da674aceffb71920bd19e2f2b8111e8d6751e09b6d9
4
+ data.tar.gz: 211ce28cd66a3ccf82c0a4da54db92c6660f5331081336e2bb721fa4b0891ef7
5
+ SHA512:
6
+ metadata.gz: 49e3d014c8ea39df2caff0cab1836a4efe9ec3050cf8cc715ea14ef9aa6d0ac9fb9657d36c29b651ab2f5820ae0e4559d2105b90a558ea1a1021c414c856421d
7
+ data.tar.gz: aaad43083101faf2356e5ce17b6a800b6a5dc76aa11aee44d0e079348cc715f2e6f78f6e784a0452aea9fcf8e0485f1bd5129f979b6042b7330995878ae9d0cb
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ See the repository's [CHANGELOG.md](https://github.com/sanamhub/nepdate-ruby/blob/main/CHANGELOG.md).
4
+
5
+ ## [Unreleased]
6
+
7
+ ### Added
8
+
9
+ - The `nepdate` gem, version 1.0.0-rc.1, with Bikram Sambat dates, conversion, arithmetic,
10
+ formatting, parsing, ranges and fiscal years.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NepDate contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/NOTICE ADDED
@@ -0,0 +1,31 @@
1
+ NepDate for Ruby
2
+
3
+ This repository ports NepDate, the C# library by Raju Prasai and contributors
4
+ (https://github.com/RajuPrasai/NepDate), to Ruby. The calendar and patro data, the golden test
5
+ vectors and the behaviour this port follows all come from that library.
6
+
7
+ The calendar data in shared/data (data/calendar/, data/patro/) was extracted from
8
+ NepDate (https://github.com/RajuPrasai/NepDate, commit c6fff4f2f60ac01e31c086568320649627422ba1)
9
+ and is used under the MIT License:
10
+
11
+ MIT License
12
+
13
+ Copyright (c) 2023 NepDate and contributors
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # nepdate
2
+
3
+ Bikram Sambat (Nepali calendar) dates for Ruby: conversion to and from Gregorian, arithmetic with
4
+ clamp and spill, formatting and parsing in English and Nepali, inclusive ranges and fiscal years.
5
+ Pure Ruby, Ruby 3.4 or newer, no runtime dependency.
6
+
7
+ ```ruby
8
+ require "nepdate"
9
+
10
+ date = NepDate::Date.from_bs(2081, 4, 15)
11
+ puts date # 2081/04/15
12
+ puts date.to_date # 2024-07-30
13
+ puts date.to_long_string(weekday: true)
14
+ ```
15
+
16
+ `nepdate-patro` adds tithi, public holidays and events. The full API is in the repository's
17
+ [docs/API.md](https://github.com/sanamhub/nepdate-ruby/blob/main/docs/API.md). Part of the NepDate
18
+ family; the data and behaviour come from the hub
19
+ [`sanamhub/nepdate`](https://github.com/sanamhub/nepdate) and the C# original
20
+ [NepDate](https://github.com/RajuPrasai/NepDate).
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NepDate
4
+ # BS serial arithmetic and the proleptic Gregorian conversion of ALGORITHM.md sections 3 to 6.
5
+ # @api private
6
+ module Calendar
7
+ GREGORIAN_MONTH_LENGTHS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31].freeze
8
+
9
+ module_function
10
+
11
+ def month_length(year, month)
12
+ index = year - CalendarTable::MIN_YEAR
13
+ unless index >= 0 && index < CalendarTable::YEARS
14
+ raise OutOfRangeError, "year #{year} is outside #{CalendarTable::MIN_YEAR}..#{CalendarTable::MAX_YEAR}"
15
+ end
16
+ unless month.between?(1, 12)
17
+ raise InvalidMonthError, "month #{month} is outside 1..12"
18
+ end
19
+
20
+ packed = CalendarTable::PACKED.fetch(index)
21
+ 29 + ((packed >> (2 * (month - 1))) & 0b11)
22
+ end
23
+
24
+ def to_serial(year, month, day)
25
+ CalendarTable::MONTH_START.fetch((year - CalendarTable::MIN_YEAR) * 12 + month - 1) + day - 1
26
+ end
27
+
28
+ def validate(year, month, day)
29
+ unless year.between?(CalendarTable::MIN_YEAR, CalendarTable::MAX_YEAR)
30
+ raise OutOfRangeError, "year #{year} is outside #{CalendarTable::MIN_YEAR}..#{CalendarTable::MAX_YEAR}"
31
+ end
32
+ unless month.between?(1, 12)
33
+ raise InvalidMonthError, "month #{month} is outside 1..12"
34
+ end
35
+
36
+ length = month_length(year, month)
37
+ unless day.between?(1, length)
38
+ raise InvalidDayError, "day #{day} is outside 1..#{length}"
39
+ end
40
+
41
+ true
42
+ end
43
+
44
+ # Proleptic Gregorian civil date to days since 1970-01-01, by Howard Hinnant's algorithm.
45
+ def days_from_civil(year, month, day)
46
+ year -= 1 if month <= 2
47
+ era = year.div(400)
48
+ year_of_era = year - era * 400
49
+ month_prime = (month + 9) % 12
50
+ day_of_year = (153 * month_prime + 2) / 5 + day - 1
51
+ day_of_era = year_of_era * 365 + year_of_era / 4 - year_of_era / 100 + day_of_year
52
+ era * 146097 + day_of_era - 719_468
53
+ end
54
+
55
+ def civil_from_days(days)
56
+ days += 719_468
57
+ era = days.div(146_097)
58
+ day_of_era = days - era * 146_097
59
+ year_of_era = (day_of_era - day_of_era / 1460 + day_of_era / 36_524 - day_of_era / 146_096) / 365
60
+ year = year_of_era + era * 400
61
+ day_of_year = day_of_era - (365 * year_of_era + year_of_era / 4 - year_of_era / 100)
62
+ month_prime = (5 * day_of_year + 2) / 153
63
+ day = day_of_year - (153 * month_prime + 2) / 5 + 1
64
+ month = (month_prime < 10) ? month_prime + 3 : month_prime - 9
65
+ year += 1 if month <= 2
66
+ [year, month, day]
67
+ end
68
+
69
+ def gregorian_month_length(year, month)
70
+ return 29 if month == 2 && gregorian_leap_year?(year)
71
+
72
+ GREGORIAN_MONTH_LENGTHS.fetch(month - 1)
73
+ end
74
+
75
+ def gregorian_leap_year?(year)
76
+ (year % 4).zero? && !(year % 100).zero? || (year % 400).zero?
77
+ end
78
+
79
+ def valid_gregorian?(year, month, day)
80
+ return false unless (1..12).cover?(month)
81
+
82
+ (1..gregorian_month_length(year, month)).cover?(day)
83
+ end
84
+ end
85
+ end