lunar_calendar 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 98a2793caf8f76e1eda5668de1d1ae67b30ce24411e80f14402cbb90b1a11ef4
4
+ data.tar.gz: 921e3dfb0fb431293f8e8f47c42ed20d31ea5867401421ac8b07979de9dfe97d
5
+ SHA512:
6
+ metadata.gz: 30bceb3fad47074ac31226db31d12b3bc6ec54a9ac24fc30e817d274372d28f25c602f45afa119b02fe63ac44434038e8b18165c9b77fac02c6b9eed21381ce1
7
+ data.tar.gz: f68df0d348d325f053103af9f875c16129f16f3633724d2754a4061ec942cdf2d92ea6fcab38d6c28070b54c879955a560326c65c4231299315e51bb41e44dcb
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,15 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6.3
3
+
4
+
5
+ Style/HashEachMethods:
6
+ Enabled: true
7
+ Style/HashTransformKeys:
8
+ Enabled: true
9
+ Style/HashTransformValues:
10
+ Enabled: true
11
+
12
+ Metrics/BlockLength:
13
+ Exclude:
14
+ - spec/**/*_spec.rb
15
+
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.6.3
6
+ before_install: gem install bundler -v 2.1.2
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at elct9620@frost.tw. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in lunar_calendar.gemspec
6
+ gemspec
7
+
8
+ gem 'rake', '~> 12.0'
9
+ gem 'rspec', '~> 3.0'
@@ -0,0 +1,52 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lunar_calendar (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.0)
10
+ diff-lcs (1.3)
11
+ jaro_winkler (1.5.4)
12
+ parallel (1.19.1)
13
+ parser (2.7.1.0)
14
+ ast (~> 2.4.0)
15
+ rainbow (3.0.0)
16
+ rake (12.3.3)
17
+ rexml (3.2.4)
18
+ rspec (3.9.0)
19
+ rspec-core (~> 3.9.0)
20
+ rspec-expectations (~> 3.9.0)
21
+ rspec-mocks (~> 3.9.0)
22
+ rspec-core (3.9.1)
23
+ rspec-support (~> 3.9.1)
24
+ rspec-expectations (3.9.0)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.9.0)
27
+ rspec-mocks (3.9.1)
28
+ diff-lcs (>= 1.2.0, < 2.0)
29
+ rspec-support (~> 3.9.0)
30
+ rspec-support (3.9.2)
31
+ rubocop (0.80.1)
32
+ jaro_winkler (~> 1.5.1)
33
+ parallel (~> 1.10)
34
+ parser (>= 2.7.0.1)
35
+ rainbow (>= 2.2.2, < 4.0)
36
+ rexml
37
+ ruby-progressbar (~> 1.7)
38
+ unicode-display_width (>= 1.4.0, < 1.7)
39
+ ruby-progressbar (1.10.1)
40
+ unicode-display_width (1.6.1)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ lunar_calendar!
47
+ rake (~> 12.0)
48
+ rspec (~> 3.0)
49
+ rubocop (~> 0.80.1)
50
+
51
+ BUNDLED WITH
52
+ 2.1.2
@@ -0,0 +1,67 @@
1
+ # LunarCalendar
2
+
3
+ Convert Solar Date to Lunar Date
4
+
5
+ ## Reference
6
+
7
+ * Table data from [isee15/Lunar-Solar-Calendar-Converter](https://github.com/isee15/Lunar-Solar-Calendar-Converter)
8
+ * Calculate discussion from [https://destiny.to/](https://destiny.to/ubbthreads/ubbthreads.php/ubb/showflat/Number/92769/site_id/1#import)
9
+
10
+ ## Data Structure
11
+
12
+ ### LunarCalendar::Data::NEW_YEARS
13
+
14
+ Each value stores the Chinese New Year date in solar calendar
15
+
16
+ | Name | Length
17
+ |------|--------
18
+ | Year | 12 bit
19
+ | Month | 4 bit
20
+ | Day | 5 bit
21
+
22
+ ### LunarCalendar::Data::LEAP_MONTHS
23
+
24
+ Each value stores the month days and leap month
25
+
26
+ | Name | Length | Description
27
+ |------|--------|--------------
28
+ | Leap Month | 4 bit | `0` means this year no leap month
29
+ | Months | 12 bit | `1` is 30 days and `0` is 29 days
30
+
31
+ ## Installation
32
+
33
+ Add this line to your application's Gemfile:
34
+
35
+ ```ruby
36
+ gem 'lunar_calendar'
37
+ ```
38
+
39
+ And then execute:
40
+
41
+ $ bundle install
42
+
43
+ Or install it yourself as:
44
+
45
+ $ gem install lunar_calendar
46
+
47
+ ## Usage
48
+
49
+ ```ruby
50
+ LunarCalendar.at_lunar(2020, 1, 1)
51
+ # => #<LunarCalendar::Lunar @year=2019 @month=12 @day=7>
52
+ ```
53
+
54
+ ## Development
55
+
56
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
57
+
58
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
59
+
60
+ ## Contributing
61
+
62
+ Bug reports and pull requests are welcome on GitHub at https://github.com/elct9620/lunar_calendar. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/elct9620/lunar_calendar/blob/master/CODE_OF_CONDUCT.md).
63
+
64
+
65
+ ## Code of Conduct
66
+
67
+ Everyone interacting in the LunarCalendar project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/elct9620/lunar_calendar/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'lunar_calendar'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lunar_calendar/version'
4
+ require 'lunar_calendar/solar'
5
+ require 'lunar_calendar/lunar'
6
+
7
+ # The Lunar Calendar Calculator
8
+ module LunarCalendar
9
+ # @since 0.1.0
10
+ SUPPORT_YEARS = (1888..2100).freeze
11
+
12
+ # Convert Solar to Lunar
13
+ #
14
+ # @param year [Number] year
15
+ # @param month [Number] month
16
+ # @param day [Number] day
17
+ #
18
+ # @return [LunarCalendar::Solar] the lunar date
19
+ #
20
+ # @since 0.1.0
21
+ def self.at_lunar(year, month, day)
22
+ Solar.new(year, month, day).to_lunar
23
+ end
24
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lunar_calendar/data/new_years'
4
+ require 'lunar_calendar/utils'
5
+ require 'lunar_calendar/lunar_year'
6
+
7
+ module LunarCalendar
8
+ module Calculator
9
+ # The Lunar Date Calculator
10
+ class Lunar
11
+ # @param date [LunarCalendar::Solar] the solar date
12
+ #
13
+ # @since 0.1.0
14
+ def initialize(solar)
15
+ @solar = solar
16
+ @lunar_year = LunarYear.new(position)
17
+ @year = position + LunarCalendar::SUPPORT_YEARS.begin
18
+ @month = 1
19
+ @day = 1
20
+ end
21
+
22
+ # @return [LunarCalendar::Lunar] the lunar date
23
+ #
24
+ # @since 0.1.0
25
+ def perform
26
+ move_days
27
+
28
+ @month -= 1 if leap?
29
+
30
+ LunarCalendar::Lunar.new(@year, @month, @day, leap_month?)
31
+ end
32
+
33
+ # @return [Number] position of table
34
+ #
35
+ # @since 0.1.0
36
+ def position
37
+ return @position unless @position.nil?
38
+
39
+ index = @solar.year - LunarCalendar::SUPPORT_YEARS.begin
40
+ # If new years in the previous year
41
+ index -= 1 if LunarCalendar::Data::NEW_YEARS[index] > @solar.binary
42
+ @position = index
43
+ end
44
+
45
+ private
46
+
47
+ def leap_month?
48
+ return false if @month != @lunar_year.leap_month + 1
49
+
50
+ true
51
+ end
52
+
53
+ def leap?
54
+ return false if @lunar_year.leap_month.zero?
55
+ return false if @lunar_year.leap_month >= @month
56
+
57
+ true
58
+ end
59
+
60
+ def move_days
61
+ @day = offset + 1
62
+ @lunar_year.month_days.each do |days_in_month|
63
+ break if days_in_month >= @day
64
+
65
+ @month += 1
66
+ @day -= days_in_month
67
+ end
68
+ end
69
+
70
+ def offset
71
+ @offset ||=
72
+ @solar.to_i - LunarCalendar::Utils.new_year_at(position).to_i
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LunarCalendar
4
+ module Data
5
+ # @since 0.1.0
6
+ LEAP_MONTHS = [
7
+ 0x1694, 0x16AA, 0x4AD5, 0xAB6,
8
+ 0xC4B7, 0x4AE, 0xA56, 0xB52A,
9
+ 0x1D2A, 0xD54, 0x75AA, 0x156A,
10
+ 0x1096D, 0x95C, 0x14AE, 0xAA4D,
11
+ 0x1A4C, 0x1B2A, 0x8D55, 0xAD4,
12
+ 0x135A, 0x495D, 0x95C, 0xD49B,
13
+ 0x149A, 0x1A4A, 0xBAA5, 0x16A8,
14
+ 0x1AD4, 0x52DA, 0x12B6, 0XE937,
15
+ 0x92E, 0x1496, 0xB64B, 0xD4A,
16
+ 0xDA8, 0x95B5, 0x56C, 0x12AE,
17
+ 0x492F, 0x92E, 0xCC96, 0x1A94,
18
+ 0x1D4A, 0xADA9, 0xB5A, 0x56C,
19
+ 0x726E, 0x125C, 0xF92D, 0x192A,
20
+ 0x1A94, 0xDB4A, 0x16AA, 0xAD4,
21
+ 0x955B, 0x4BA, 0x125A, 0x592B,
22
+ 0x152A, 0xF695, 0xD94, 0x16AA,
23
+ 0xAAB5, 0x9B4, 0x14B6, 0x6A57,
24
+ 0xA56, 0x1152A, 0x1D2A, 0xD54,
25
+ 0xD5AA, 0x156A, 0x96C, 0x94AE,
26
+ 0x14AE, 0xA4C, 0x7D26, 0x1B2A,
27
+ 0XEB55, 0xAD4, 0x12DA, 0xA95D,
28
+ 0x95A, 0x149A, 0x9A4D, 0x1A4A,
29
+ 0x11AA5, 0x16A8, 0x16D4, 0xD2DA,
30
+ 0x12B6, 0x936, 0x9497, 0x1496,
31
+ 0x1564B, 0xD4A, 0xDA8, 0xD5B4,
32
+ 0x156C, 0x12AE, 0xA92F, 0x92E,
33
+ 0xC96, 0x6D4A, 0x1D4A, 0x10D65,
34
+ 0xB58, 0x156C, 0xB26D, 0x125C,
35
+ 0x192C, 0x9A95, 0x1A94, 0x1B4A,
36
+ 0x4B55, 0xAD4, 0xF55B, 0x4BA,
37
+ 0x125A, 0xB92B, 0x152A, 0x1694,
38
+ 0x96AA, 0x15AA, 0x12AB5, 0x974,
39
+ 0x14B6, 0xCA57, 0xA56, 0x1526,
40
+ 0x8E95, 0xD54, 0x15AA, 0x49B5,
41
+ 0x96C, 0xD4AE, 0x149C, 0x1A4C,
42
+ 0xBD26, 0x1AA6, 0xB54, 0x6D6A,
43
+ 0x12DA, 0x1695D, 0x95A, 0x149A,
44
+ 0xDA4B, 0x1A4A, 0x1AA4, 0xBB54,
45
+ 0x16B4, 0xADA, 0x495B, 0x936,
46
+ 0xF497, 0x1496, 0x154A, 0xB6A5,
47
+ 0xDA4, 0x15B4, 0x6AB6, 0x126E,
48
+ 0x1092F, 0x92E, 0xC96, 0xCD4A,
49
+ 0x1D4A, 0xD64, 0x956C, 0x155C,
50
+ 0x125C, 0x792E, 0x192C, 0xFA95,
51
+ 0x1A94, 0x1B4A, 0xAB55, 0xAD4,
52
+ 0x14DA, 0x8A5D, 0xA5A, 0x1152B,
53
+ 0x152A, 0x1694, 0xD6AA, 0x15AA,
54
+ 0xAB4, 0x94BA, 0x14B6, 0xA56,
55
+ 0x7527, 0xD26, 0XEE53, 0xD54,
56
+ 0x15AA, 0xA9B5, 0x96C, 0x14AE,
57
+ 0x8A4E, 0x1A4C, 0x11D26, 0x1AA4,
58
+ 0x1B54, 0xCD6A, 0xADA, 0x95C,
59
+ 0x949D, 0x149A, 0x1A2A, 0x5B25,
60
+ 0x1AA4, 0xFB52, 0x16B4, 0xABA,
61
+ 0xA95B, 0x936, 0x1496, 0x9A4B,
62
+ 0x154A, 0x136A5, 0xDA4, 0x15AC
63
+ ].freeze
64
+ end
65
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LunarCalendar
4
+ module Data
5
+ # @since 0.1.0
6
+ NEW_YEARS = [
7
+ 0xec04c, 0xec23f, 0xec435, 0xec649,
8
+ 0xec83e, 0xeca51, 0xecc46, 0xece3a,
9
+ 0xed04d, 0xed242, 0xed436, 0xed64a,
10
+ 0xed83f, 0xeda53, 0xedc48, 0xede3d,
11
+ 0xee050, 0xee244, 0xee439, 0xee64d,
12
+ 0xee842, 0xeea36, 0xeec4a, 0xeee3e,
13
+ 0xef052, 0xef246, 0xef43a, 0xef64e,
14
+ 0xef843, 0xefa37, 0xefc4b, 0xefe41,
15
+ 0xf0054, 0xf0248, 0xf043c, 0xf0650,
16
+ 0xf0845, 0xf0a38, 0xf0c4d, 0xf0e42,
17
+ 0xf1037, 0xf124a, 0xf143e, 0xf1651,
18
+ 0xf1846, 0xf1a3a, 0xf1c4e, 0xf1e44,
19
+ 0xf2038, 0xf224b, 0xf243f, 0xf2653,
20
+ 0xf2848, 0xf2a3b, 0xf2c4f, 0xf2e45,
21
+ 0xf3039, 0xf324d, 0xf3442, 0xf3636,
22
+ 0xf384a, 0xf3a3d, 0xf3c51, 0xf3e46,
23
+ 0xf403b, 0xf424e, 0xf4443, 0xf4638,
24
+ 0xf484c, 0xf4a3f, 0xf4c52, 0xf4e48,
25
+ 0xf503c, 0xf524f, 0xf5445, 0xf5639,
26
+ 0xf584d, 0xf5a42, 0xf5c35, 0xf5e49,
27
+ 0xf603e, 0xf6251, 0xf6446, 0xf663b,
28
+ 0xf684f, 0xf6a43, 0xf6c37, 0xf6e4b,
29
+ 0xf703f, 0xf7252, 0xf7447, 0xf763c,
30
+ 0xf7850, 0xf7a45, 0xf7c39, 0xf7e4d,
31
+ 0xf8042, 0xf8254, 0xf8449, 0xf863d,
32
+ 0xf8851, 0xf8a46, 0xf8c3b, 0xf8e4f,
33
+ 0xf9044, 0xf9237, 0xf944a, 0xf963f,
34
+ 0xf9853, 0xf9a47, 0xf9c3c, 0xf9e50,
35
+ 0xfa045, 0xfa238, 0xfa44c, 0xfa641,
36
+ 0xfa836, 0xfaa49, 0xfac3d, 0xfae52,
37
+ 0xfb047, 0xfb23a, 0xfb44e, 0xfb643,
38
+ 0xfb837, 0xfba4a, 0xfbc3f, 0xfbe53,
39
+ 0xfc048, 0xfc23c, 0xfc450, 0xfc645,
40
+ 0xfc839, 0xfca4c, 0xfcc41, 0xfce36,
41
+ 0xfd04a, 0xfd23d, 0xfd451, 0xfd646,
42
+ 0xfd83a, 0xfda4d, 0xfdc43, 0xfde37,
43
+ 0xfe04b, 0xfe23f, 0xfe453, 0xfe648,
44
+ 0xfe83c, 0xfea4f, 0xfec44, 0xfee38,
45
+ 0xff04c, 0xff241, 0xff436, 0xff64a,
46
+ 0xff83e, 0xffa51, 0xffc46, 0xffe3a,
47
+ 0x10004e, 0x100242, 0x100437, 0x10064b,
48
+ 0x100841, 0x100a53, 0x100c48, 0x100e3c,
49
+ 0x10104f, 0x101244, 0x101438, 0x10164c,
50
+ 0x101842, 0x101a35, 0x101c49, 0x101e3d,
51
+ 0x102051, 0x102245, 0x10243a, 0x10264e,
52
+ 0x102843, 0x102a37, 0x102c4b, 0x102e3f,
53
+ 0x103053, 0x103247, 0x10343b, 0x10364f,
54
+ 0x103845, 0x103a38, 0x103c4c, 0x103e42,
55
+ 0x104036, 0x104249, 0x10443d, 0x104651,
56
+ 0x104846, 0x104a3a, 0x104c4e, 0x104e43,
57
+ 0x105038, 0x10524a, 0x10543e, 0x105652,
58
+ 0x105847, 0x105a3b, 0x105c4f, 0x105e45,
59
+ 0x106039, 0x10624c, 0x106441, 0x106635,
60
+ 0x106849, 0x106a3d, 0x106c51, 0x106e47,
61
+ 0x10703c, 0x10724f, 0x107444, 0x107638,
62
+ 0x10784c, 0x107a3f, 0x107c53, 0x107e48
63
+ ].freeze
64
+ end
65
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LunarCalendar
4
+ # The abstract date of calendar
5
+ class Date
6
+ include Comparable
7
+
8
+ # @since 0.1.0
9
+ attr_reader :year, :month, :day
10
+
11
+ # @param year [Number] year
12
+ # @param month [Number] month
13
+ # @param day [Number] day
14
+ #
15
+ # @since 0.1.0
16
+ def initialize(year, month, day)
17
+ @year = year
18
+ @month = month
19
+ @day = day
20
+ end
21
+
22
+ # @return [Number] the number of days
23
+ #
24
+ # @since 0.1.0
25
+ def to_i
26
+ -1
27
+ end
28
+
29
+ # @return [Number] the packed solar date
30
+ #
31
+ # @since 0.1.0
32
+ def binary
33
+ @binary ||= (@year << 9) | (@month << 5) | @day
34
+ end
35
+
36
+ # @return [Boolean] date is same or not
37
+ #
38
+ # @since 0.1.0
39
+ def ==(other)
40
+ return false unless other.is_a?(self.class)
41
+
42
+ @year == other.year &&
43
+ @month == other.month &&
44
+ @day == other.day
45
+ end
46
+
47
+ # @return [Number] the compare result
48
+ #
49
+ # @since 0.1.0
50
+ def <=>(other)
51
+ binary <=> other.binary
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lunar_calendar/date'
4
+
5
+ module LunarCalendar
6
+ # The Lunar Calendar Date
7
+ class Lunar < Date
8
+ # @param year [Number] year
9
+ # @param month [Number] month
10
+ # @param day [Number] day
11
+ # @param leap [Boolean] is leap month
12
+ #
13
+ # @since 0.1.0
14
+ def initialize(year, month, day, leap = false)
15
+ super(year, month, day)
16
+ @leap = leap
17
+ end
18
+
19
+ # @return [Boolean] is leap month
20
+ #
21
+ # @since 0.1.0
22
+ def leap?
23
+ @leap == true
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lunar_calendar/data/leap_months'
4
+ require 'lunar_calendar/utils'
5
+
6
+ module LunarCalendar
7
+ # The leap and months of specify year
8
+ #
9
+ # @param offset [Number] the offset of table
10
+ class LunarYear
11
+ def initialize(offset)
12
+ @offset = offset
13
+ end
14
+
15
+ # @return [Number] the packed leap data
16
+ def binary
17
+ @binary ||= LunarCalendar::Data::LEAP_MONTHS[@offset]
18
+ end
19
+
20
+ # @return [Array<Number>] month days
21
+ def month_days
22
+ (0..12).map do |month|
23
+ LunarCalendar::Utils.decode(binary, 1, 12 - month) == 1 ? 30 : 29
24
+ end
25
+ end
26
+
27
+ # @return [Number] the leap month
28
+ def leap_month
29
+ @leap_month ||= LunarCalendar::Utils.decode(binary, 4, 13)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lunar_calendar/date'
4
+ require 'lunar_calendar/calculator/lunar'
5
+
6
+ module LunarCalendar
7
+ # The Solar Calendar Date
8
+ class Solar < Date
9
+ # @return [LunarCalendar::Lunar] the lunar date
10
+ #
11
+ # @since 0.1.0
12
+ def to_lunar
13
+ LunarCalendar::Calculator::Lunar.new(self).perform
14
+ end
15
+
16
+ # @return [Number] solar days
17
+ #
18
+ # @since 0.1.0
19
+ # rubocop:disable Metrics/AbcSize
20
+ def to_i
21
+ m = (@month + 9) % 12
22
+ y = @year - (m / 10)
23
+
24
+ (365 * y) + # One year have 365 days
25
+ (y / 4) - # Add leap days
26
+ (y / 100) +
27
+ (y / 400) +
28
+ ((m * 306 + 5) / 10) + # Unknown
29
+ (@day - 1)
30
+ end
31
+ # rubocop:enable Metrics/AbcSize
32
+ end
33
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lunar_calendar/data/new_years'
4
+
5
+ module LunarCalendar
6
+ # The calculate utils
7
+ module Utils
8
+ # Extract packed informactio
9
+ #
10
+ # @param data [Number] packed data
11
+ # @param length [Number] total bit to read
12
+ # @param shift [Number] the shift position
13
+ #
14
+ # @return [Number] value
15
+ #
16
+ # @since 0.1.0
17
+ def self.decode(data, length, shift)
18
+ (data & (((1 << length) - 1) << shift)) >> shift
19
+ end
20
+
21
+ # Extract lunar new year in solar date
22
+ #
23
+ # @param offset [Number] the offset of table
24
+ #
25
+ # @return [LunarCalendar::Solar] the solar date
26
+ #
27
+ # @since 0.1.0
28
+ def self.new_year_at(offset)
29
+ solar = LunarCalendar::Data::NEW_YEARS[offset]
30
+ year = decode(solar, 12, 9)
31
+ month = decode(solar, 4, 5)
32
+ day = decode(solar, 5, 0)
33
+
34
+ Solar.new(year, month, day)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LunarCalendar
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/lunar_calendar/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'lunar_calendar'
7
+ spec.version = LunarCalendar::VERSION
8
+ spec.authors = ['蒼時弦也']
9
+ spec.email = ['contact@frost.tw']
10
+
11
+ spec.summary = 'The calculator to calculate lunar calendar'
12
+ spec.description = 'The calculator to calculate lunar calendar'
13
+ spec.homepage = 'https://github.com/elct9620/lunar_calendar'
14
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
15
+
16
+ spec.metadata['homepage_uri'] = spec.homepage
17
+ spec.metadata['source_code_uri'] = 'https://github.com/elct9620/lunar_calendar'
18
+
19
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
20
+ `git ls-files -z`
21
+ .split("\x0")
22
+ .reject { |f| f.match(%r{^(test|spec|features)/}) }
23
+ end
24
+ spec.bindir = 'exe'
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ['lib']
27
+
28
+ spec.add_development_dependency 'rspec'
29
+ spec.add_development_dependency 'rubocop', '~> 0.80.1'
30
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lunar_calendar
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - 蒼時弦也
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-04-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.80.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.80.1
41
+ description: The calculator to calculate lunar calendar
42
+ email:
43
+ - contact@frost.tw
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".rspec"
50
+ - ".rubocop.yml"
51
+ - ".travis.yml"
52
+ - CODE_OF_CONDUCT.md
53
+ - Gemfile
54
+ - Gemfile.lock
55
+ - README.md
56
+ - Rakefile
57
+ - bin/console
58
+ - bin/setup
59
+ - lib/lunar_calendar.rb
60
+ - lib/lunar_calendar/calculator/lunar.rb
61
+ - lib/lunar_calendar/data/leap_months.rb
62
+ - lib/lunar_calendar/data/new_years.rb
63
+ - lib/lunar_calendar/date.rb
64
+ - lib/lunar_calendar/lunar.rb
65
+ - lib/lunar_calendar/lunar_year.rb
66
+ - lib/lunar_calendar/solar.rb
67
+ - lib/lunar_calendar/utils.rb
68
+ - lib/lunar_calendar/version.rb
69
+ - lunar_calendar.gemspec
70
+ homepage: https://github.com/elct9620/lunar_calendar
71
+ licenses: []
72
+ metadata:
73
+ homepage_uri: https://github.com/elct9620/lunar_calendar
74
+ source_code_uri: https://github.com/elct9620/lunar_calendar
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 2.3.0
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubygems_version: 3.0.3
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: The calculator to calculate lunar calendar
94
+ test_files: []