lunar_calendar 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []