date_manager 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ # Specify your gem's dependencies in date_manager.gemspec
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2015 Fernando
2
+ MIT License
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+ The above copyright notice and this permission notice shall be
11
+ included in all copies or substantial portions of the Software.
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,178 @@
1
+ [![Build Status](https://semaphoreci.com/api/v1/projects/c1127eeb-9c13-44dd-baeb-155ce4a54493/425379/badge.svg)](https://semaphoreci.com/fegoa89/date-manager)
2
+ # DateManager
3
+
4
+ Parse, validate, manipulate, and display dates.
5
+
6
+ # Start
7
+
8
+ DateManager is a gem for convert/parse/compare two strings into date a DateTime object and manipulate them .
9
+ For handle different dates format, I did this gem based on the most used formats in different countries (https://en.wikipedia.org/wiki/Date_format_by_country#Listing), from where I can divide it in three basic types :
10
+
11
+ - MDY - Month/Day/Year mm/dd/yyyy
12
+ - DMY - Day/Month/Year dd/mm/yyyy
13
+ - YMD - Year/Month/Day yyyy/mm/dd
14
+
15
+ # Using DateManager
16
+
17
+ Create an instance:
18
+
19
+ $ @dates = DateManager.new('2012/02/02', '2012/02/03')
20
+
21
+ The standard string input is the YMD format .
22
+
23
+ You can set any other string input format (Like day - month - year) passing the date format as a third parameter like :
24
+
25
+ $ @dates = DateManager.new('02/03/2015', '03/03/2015', 'DMY')
26
+
27
+ or
28
+
29
+ $ @dates = DateManager.new('12/30/2015', '12/31/2015', 'MDY')
30
+
31
+
32
+ If the format is given as a DMY ( for example) and it does not contains a third parameter that indicates that the strings given are build on this format, the first date and the last date wont be possible to get set .
33
+ You can use a '.' , '-' or '/' as a component separator for separate the different components of the dates, it will be translated into '/'.
34
+
35
+ After a succesfull creation of an object, keep in mind the date range you are passing. The first date (first string given) should be older than the second date (second string given). If not it does not have sense (you can test it calling the method '#valid_date_range?' . The purpose of this gem is play between the dates of two dates :) )
36
+
37
+ # Methods
38
+
39
+ ## start_date
40
+ Returns the start_date object :
41
+
42
+ $ @dates = DateManager.new('02/03/2015', '03/03/2015', 'DMY')
43
+ $ @dates.start_date
44
+ $ #<DateTime: 2015-03-02T00:00:00+00:00 ((2457084j,0s,0n),+0s,2299161j)>
45
+
46
+ ## finish_date
47
+ Returns the finish_date object :
48
+
49
+ $ @dates = DateManager.new('02/03/2015', '03/03/2015', 'DMY')
50
+ $ @dates.finish_date
51
+ $ #<DateTime: 2015-03-03T00:00:00+00:00 ((2457085j,0s,0n),+0s,2299161j)>
52
+
53
+ ## format
54
+ Returns the date format :
55
+
56
+ $ @dates = DateManager.new('02/03/2015', '03/03/2015', 'DMY')
57
+ $ @dates.format
58
+ $ DMY
59
+
60
+ ## valid_date_range?
61
+
62
+ Compares if the first string given is a date older than the second string given .
63
+
64
+ $ @dates = DateManager.new('02/03/2015', '03/03/2015', 'DMY')
65
+ $ @dates.valid_date_range?
66
+ $ true
67
+
68
+ ## days_between_dates
69
+
70
+ Gives back the quantity of days between these dates
71
+
72
+ $ @dates = DateManager.new('02/03/2015', '03/03/2015', 'DMY')
73
+ $ @dates.days_between_dates
74
+ $ 1
75
+
76
+ ## months_between_dates
77
+
78
+ Gives back the quantity of months between these dates
79
+
80
+ $ @dates = DateManager.new('02/02/2015', '03/03/2015', 'DMY')
81
+ $ @dates.months_between_dates
82
+ $ 1
83
+
84
+ ## years_between_dates
85
+
86
+ Gives back the quantity of years between these dates
87
+
88
+ $ @dates = DateManager.new('03/03/2014', '03/03/2015', 'DMY')
89
+ $ @dates.years_between_dates
90
+ $ 1
91
+
92
+ ## start_date_leap_year?
93
+
94
+ Returns true or false depending if the start_date object is a leap year or not
95
+ $ @dates = DateManager.new('03/03/2014', '03/03/2015', 'DMY')
96
+ $ @dates.start_date_leap_year?
97
+ $ false
98
+
99
+ ## finish_date_leap_year?
100
+
101
+ Returns true or false depending if the finish_date object is a leap year or not
102
+
103
+ Gives back the quantity of years between these dates
104
+
105
+ $ @dates = DateManager.new('03/03/2014', '03/03/2016', 'DMY')
106
+ $ @dates.finish_date_leap_year?
107
+ $ true
108
+
109
+ ## differences_between_dates
110
+
111
+ Returns a hash containing the quantity of years / months / days between the dates
112
+
113
+ $ @dates = DateManager.new('03/03/2014', '03/03/2016', 'DMY')
114
+ $ @dates.differences_between_dates
115
+ $ {:years=>2, :months=>24, :days=>731}
116
+
117
+ ## readable_days_between_dates(language = {})
118
+
119
+ Returns a string with quantity of days in between. Only Spanish and English are supported.
120
+
121
+ $ @dates = DateManager.new('02/02/2015', '03/03/2015', 'DMY')
122
+ $ @dates.readable_days_between_dates
123
+ $ 29 days
124
+
125
+ ## readable_months_between_dates(language = {})
126
+
127
+ Returns a string with the quantity of months in between. Only Spanish and English are supported.
128
+
129
+ $ @dates = DateManager.new('02/02/2015', '03/04/2015', 'DMY')
130
+ $ @dates.readable_months_between_dates
131
+ $ 2 months
132
+
133
+ ## human_readable_format
134
+
135
+ Returns a string with start_date and finish_date object in a human readable way . Only Spanish and English are supported.
136
+
137
+ $ @dates = DateManager.new('2012/02/01', '2012/02/03')
138
+ $ @dates.human_readable_format
139
+ $ "First date : February 01, 2012 Wednesday - Second date : February 03, 2012 Friday"
140
+
141
+ ## working_days
142
+
143
+ Return quantity of working days between dates
144
+
145
+ $ @dates = DateManager.new('2012/02/01', '2012/02/03')
146
+ $ @dates.working_days
147
+ $ 3
148
+
149
+ ## total_weekend_days
150
+
151
+ Return quantity of saturdays / sundays between dates
152
+
153
+ $ @dates = DateManager.new('2015/01/30', '2015/02/13')
154
+ $ @dates.total_weekend_days
155
+ $ 4
156
+
157
+ # Installation
158
+
159
+ Add this line to your application's Gemfile:
160
+
161
+ gem 'date_manager'
162
+
163
+ And then execute:
164
+
165
+ $ bundle
166
+
167
+ Or install it yourself as:
168
+
169
+ $ gem install date_manager
170
+
171
+
172
+ # Contributing
173
+
174
+ 1. Fork it
175
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
176
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
177
+ 4. Push to the branch (`git push origin my-new-feature`)
178
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'date_manager/version'
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "date_manager"
7
+ spec.version = DateManager::VERSION
8
+ spec.authors = ["Fernando"]
9
+ spec.email = ["fgonzalezaguilera@gmail.com"]
10
+ spec.description = %q{Parse, validate, manipulate, and display dates.}
11
+ spec.summary = %q{}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+ spec.files = `git ls-files`.split($/)
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+ spec.add_development_dependency "bundler", "~> 1.3"
19
+ spec.add_development_dependency "rake"
20
+ spec.add_development_dependency 'rspec'
21
+ end
@@ -0,0 +1,87 @@
1
+ require 'date'
2
+ require 'yaml'
3
+ require 'date_manager/version'
4
+ require 'date_manager/date_parser'
5
+ require 'date_manager/human_readable_parser'
6
+
7
+ class DateManager
8
+
9
+ attr_accessor :start_date, :finish_date, :format
10
+
11
+ def initialize(start_date, finish_date, format = {})
12
+ @start_date, @finish_date = initialize_date_parser(start_date, finish_date, format).parse
13
+ @format = initialize_date_parser(start_date, finish_date, format).format
14
+ end
15
+
16
+ def valid_date_range?
17
+ # Compares if the start_date is lower than finish_date
18
+ @start_date < @finish_date
19
+ end
20
+
21
+ def days_between_dates
22
+ if valid_date_range?
23
+ @finish_date.mjd - @start_date.mjd
24
+ end
25
+ end
26
+
27
+ def months_between_dates
28
+ if valid_date_range?
29
+ (@finish_date.year * 12 + @finish_date.month) - (@start_date.year * 12 + @start_date.month)
30
+ end
31
+ end
32
+
33
+ def years_between_dates
34
+ if valid_date_range?
35
+ @finish_date.year - @start_date.year
36
+ end
37
+ end
38
+
39
+ def start_date_leap_year?
40
+ # Determines if a year is a leap year
41
+ Date.leap?( @start_date.year )
42
+ end
43
+
44
+ def finish_date_leap_year?
45
+ # Determines if a year is a leap year
46
+ Date.leap?( @finish_date.year )
47
+ end
48
+
49
+ def differences_between_dates
50
+ # Returns a hash that includes the quantity of years, months and days between
51
+ { years: years_between_dates, months: months_between_dates, days: days_between_dates }
52
+ end
53
+
54
+ def readable_days_between_dates(language = {})
55
+ # returns a string with the quantity of days between dates
56
+ if valid_date_range?
57
+ HumanReadableParser.days_between_dates( days_between_dates, language)
58
+ end
59
+ end
60
+
61
+ def human_readable_format(language = {})
62
+ # returns a string with start_date and finish_date object in a human readable way
63
+ HumanReadableParser.to_human_readable_date(@start_date, @finish_date, language)
64
+ end
65
+
66
+ def readable_months_between_dates(language = {})
67
+ # returns a string with the quantity of months between dates
68
+ HumanReadableParser.months_between_dates(months_between_dates, language)
69
+ end
70
+
71
+ def working_days
72
+ # Return quantity of working days
73
+ (@start_date..@finish_date).select{ |day| (1..5).include?(day.wday) }.length
74
+ end
75
+
76
+ def total_weekend_days
77
+ # Return quantity of weekend days
78
+ (@start_date..@finish_date).select{ |day| [0, 6].include?(day.wday) }.length
79
+ end
80
+
81
+ private
82
+
83
+ def initialize_date_parser(start_date, finish_date, format)
84
+ DateParser.new(start_date, finish_date, format)
85
+ end
86
+
87
+ end
@@ -0,0 +1,93 @@
1
+ class DateParser
2
+ # Valid date formats by country - based on https://en.wikipedia.org/wiki/Date_format_by_country#Listing
3
+ # Dates formats
4
+ # MDY -> mm/dd/yyyy DateTime.parse("6/15/2012", '%m/%d/%Y') - ^\d{2}(-|.|\/)\d{2}(-|.|\/)\d{4}$
5
+ # DMY -> dd/mm/yyyy DateTime.parse("15/6/2012", '%d/%m/%Y') - ^\d{2}(-|.|\/)\d{2}(-|.|\/)\d{4}$
6
+ # YMD -> yyyy/mm/dd DateTime.parse("2012/6/15", '%Y/%m/%d') - ^\d{4}(-|.|\/)\d{2}(-|.|\/)\d{2}$ with seconds '^\d{4}(-|.|\/)\d{2}(-|.|\/)\d{2} \d{2}:\d{2}:\d{2}$/', '2008-09-01 12:35:45'
7
+ # DateParser.new('02/02/2012','02/02/2013', 'DMY')
8
+ attr_accessor :start_date, :finish_date, :format
9
+
10
+ OTHER_COMPONENT_SEPARATOR = {'.' => '/', '-' => '/'}
11
+ DATE_FORMAT = ['MDY', 'DMY', 'YMD']
12
+
13
+ def initialize(start_date, finish_date, format = '')
14
+ @format = get_format(format)
15
+ @start_date = start_date
16
+ @finish_date = finish_date
17
+ end
18
+
19
+ def parse
20
+ if valid_country_format_date?
21
+ parse_date
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def valid_country_format_date?
28
+ # Check if the format given is included into the date formats we can handle
29
+ DATE_FORMAT.include?(@format)
30
+ end
31
+
32
+ def get_format(format)
33
+ # If there is no format present, automatically assigns 'YMD' date format
34
+ ( format.nil? || format.empty? ) ? 'YMD' : analyze_format_string(format.upcase)
35
+ end
36
+
37
+ def analyze_format_string(format)
38
+ DATE_FORMAT.include?(format.upcase) ? format : nil
39
+ end
40
+
41
+ def has_correct_structure?(regex)
42
+ # Compares the string given for both dates with the regex expresion for
43
+ # this date format
44
+ @start_date =~ regex && @start_date =~ regex
45
+ end
46
+
47
+ def parse_date
48
+ # Validates and convert the string based on the date format
49
+ case @format
50
+ when 'MDY'
51
+ validate_string(date_format_structure[:mdy])
52
+ when 'DMY'
53
+ validate_string(date_format_structure[:dmy])
54
+ else
55
+ validate_string(date_format_structure[:ymd])
56
+ end
57
+ end
58
+
59
+ def validate_string(date_format)
60
+ # If the structure of the string coincides with the regex expression for this date format
61
+ # then it cleans the string if it contains the dates separated with '.' or '-'
62
+ # and convert it to an Date object
63
+ if has_correct_structure?(date_format[:regex])
64
+ clean_date_separator
65
+ convert_to_date_object(date_format[:structure])
66
+ end
67
+ end
68
+
69
+ def clean_date_separator
70
+ OTHER_COMPONENT_SEPARATOR.each do |key, value|
71
+ @start_date.gsub!(key, value) if @start_date.include?(key)
72
+ @finish_date.gsub!(key, value) if @finish_date.include?(key)
73
+ end
74
+ end
75
+
76
+ def date_format_structure
77
+ # Hash that contains the structure that this date format has (m - Month, d - Day, Y - Year)
78
+ # for be parsed to a valid Date object.
79
+ # Contains the regular expression for compare the exact position of the day, month
80
+ # and year, depending on the date format
81
+ {
82
+ mdy: { structure: '%m/%d/%Y', regex: /^\d{2}(-|.|\/)\d{2}(-|.|\/)\d{4}$/ },
83
+ dmy: { structure: '%d/%m/%Y', regex: /^\d{2}(-|.|\/)\d{2}(-|.|\/)\d{4}$/ },
84
+ ymd: { structure: '%Y/%m/%d', regex: /^\d{4}(-|.|\/)\d{2}(-|.|\/)\d{2}$/ }
85
+ }
86
+ end
87
+
88
+ def convert_to_date_object(structure)
89
+ # Returns two Date objects
90
+ [ DateTime.parse(@start_date, structure), DateTime.parse(@finish_date, structure) ]
91
+ end
92
+
93
+ end
@@ -0,0 +1,26 @@
1
+ class HumanReadableParser
2
+
3
+ def self.to_human_readable_date(start_date, finish_date, language = {})
4
+ load_translation(language)["long_readable_format"] % { first_date: "#{start_date.strftime("%B %d, %Y %A")}", last_date: "#{finish_date.strftime("%B %d, %Y %A")}" }
5
+ end
6
+
7
+ def self.days_between_dates(days, language = {})
8
+ load_translation(language)["days_between_dates"] % { total_days: days }
9
+ end
10
+
11
+ def self.months_between_dates(months, language = {})
12
+ load_translation(language)["months_between_dates"] % { total_months: months }
13
+ end
14
+
15
+ private
16
+
17
+ def self.load_translation(language)
18
+ # Loads translation.yml
19
+ if not language.empty?
20
+ @file ||= YAML.load_file("lib/translations/translation.yml")[language]
21
+ else
22
+ @sfile ||= YAML.load_file("lib/translations/translation.yml")['en']
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,3 @@
1
+ class DateManager
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,9 @@
1
+ en:
2
+ long_readable_format: 'First date : %{first_date} - Second date : %{last_date}'
3
+ days_between_dates: '%{total_days} days'
4
+ months_between_dates: '%{total_months} months'
5
+
6
+ es:
7
+ long_readable_format: 'Primera Fecha : %{first_date} - Segunda Fecha : %{last_date}'
8
+ days_between_dates: '%{total_days} dias'
9
+ months_between_dates: '%{total_months} meses'
@@ -0,0 +1,264 @@
1
+ require 'date_manager'
2
+
3
+ describe DateManager do
4
+
5
+ describe '#initialize' do
6
+ context 'with valid params given' do
7
+ cases = [ { first_date: '2012/02/02', second_date: '2012/02/03' , format: 'YMD', date_structure: '%Y/%m/%d' },
8
+ { first_date: '2012.02.02', second_date: '2012.02.03' , format: 'YMD', date_structure: '%Y/%m/%d' },
9
+ { first_date: '2012-02-02', second_date: '2012-02-03' , format: 'YMD', date_structure: '%Y/%m/%d' },
10
+ { first_date: '01/02/2015', second_date: '01/03/2015' , format: 'MDY', date_structure: '%m/%d/%Y' },
11
+ { first_date: '01.02.2015', second_date: '01.03.2015' , format: 'MDY', date_structure: '%m/%d/%Y' },
12
+ { first_date: '01-02-2015', second_date: '01-03-2015' , format: 'MDY', date_structure: '%m/%d/%Y' },
13
+ { first_date: '01/03/2015', second_date: '02/03/2015' , format: 'DMY', date_structure: '%d/%m/%Y' },
14
+ { first_date: '01.03.2015', second_date: '02.03.2015' , format: 'DMY', date_structure: '%d/%m/%Y' },
15
+ { first_date: '01-03-2015', second_date: '02-03-2015' , format: 'DMY', date_structure: '%d/%m/%Y' } ]
16
+
17
+ cases.each do |example|
18
+
19
+ let(:first_date_to_date) { DateTime.parse( example[:first_date], example[:date_structure]) }
20
+
21
+ let(:second_date_to_date) { DateTime.parse( example[:second_date], example[:second_date]) }
22
+
23
+ let(:format) { example[:format] }
24
+
25
+ subject { DateManager.new( example[:first_date], example[:second_date], format ) }
26
+
27
+ it 'sets a date object on @start_date' do
28
+ expect( subject.start_date ).to eq( first_date_to_date )
29
+ end
30
+
31
+ it 'sets a date object on @finish_date' do
32
+ expect( subject.finish_date ).to eq( second_date_to_date )
33
+ end
34
+
35
+ it 'sets the format' do
36
+ expect( subject.format ).to eq( format )
37
+ end
38
+
39
+ end
40
+ end
41
+
42
+ context 'when no date format is given' do
43
+
44
+ ymd_cases = [ { first_date: '2012/02/02', second_date: '2012/02/03', date_structure: '%Y/%m/%d' },
45
+ { first_date: '2012.02.02', second_date: '2012.02.03', date_structure: '%Y/%m/%d' },
46
+ { first_date: '2012-02-02', second_date: '2012-02-03', date_structure: '%Y/%m/%d' } ]
47
+
48
+ context 'and the format dates have YMD format' do
49
+ ymd_cases.each do |example|
50
+
51
+ let(:first_date_to_date) { DateTime.parse( example[:first_date], example[:date_structure]) }
52
+
53
+ let(:second_date_to_date) { DateTime.parse( example[:second_date], example[:second_date]) }
54
+
55
+ subject { DateManager.new( example[:first_date], example[:second_date] ) }
56
+
57
+ it 'only allow date strings with YMD format' do
58
+ expect( subject.start_date ).to eq( first_date_to_date )
59
+ end
60
+
61
+ it 'sets format to YMD' do
62
+ expect( subject.format ).to eq( 'YMD' )
63
+ end
64
+
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ context 'and the format dates are not YMD' do
71
+ cases = [ { first_date: '01/02/2015', second_date: '01/03/2015' , date_structure: '%m/%d/%Y' },
72
+ { first_date: '01.02.2015', second_date: '01.03.2015' , date_structure: '%m/%d/%Y' },
73
+ { first_date: '01-02-2015', second_date: '01-03-2015' , date_structure: '%m/%d/%Y' },
74
+ { first_date: '01/03/2015', second_date: '02/03/2015' , date_structure: '%d/%m/%Y' },
75
+ { first_date: '01.03.2015', second_date: '02.03.2015' , date_structure: '%d/%m/%Y' },
76
+ { first_date: '01-03-2015', second_date: '02-03-2015' , date_structure: '%d/%m/%Y' } ]
77
+
78
+ cases.each do |ymd|
79
+
80
+ subject { DateManager.new( ymd[:first_date], ymd[:second_date] ) }
81
+
82
+ it 'does not allow to set an object when no format is given and the date format is not YMD' do
83
+ expect( subject.start_date ).to eq( nil )
84
+ expect( subject.finish_date ).to eq( nil )
85
+ end
86
+
87
+ end
88
+ end
89
+
90
+ end
91
+
92
+ describe '#valid_date_range?' do
93
+
94
+ context 'when the first date is smaller than the second date' do
95
+ it 'the result is true' do
96
+ expect( DateManager.new( '01/02/2015', '01/03/2015', 'DMY' ).valid_date_range? ).to be true
97
+ end
98
+ end
99
+
100
+ context 'when the first date is bigger than the second date' do
101
+ it 'the result is true' do
102
+ expect( DateManager.new( '02/03/2015', '01/03/2015', 'DMY' ).valid_date_range? ).to be false
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ describe '#days_between_dates' do
109
+
110
+ context 'with start date "01/02/2015" and finish date 01/03/2015' do
111
+ it 'the result is 28' do
112
+ expect( DateManager.new( '01/02/2015', '01/03/2015', 'DMY' ).days_between_dates ).to eq(28)
113
+ end
114
+ end
115
+
116
+ context 'without a valid date range' do
117
+ it 'the result is nil' do
118
+ expect( DateManager.new( '02/03/2015', '01/03/2015', 'DMY' ).days_between_dates ).to eq(nil)
119
+ end
120
+ end
121
+
122
+ end
123
+
124
+ describe '#months_between_dates' do
125
+
126
+ cases = [ { first_date: '01/02/2015', second_date: '01/03/2015' , expected_result: 1 },
127
+ { first_date: '01/02/2015', second_date: '02/02/2015' , expected_result: 0 },
128
+ { first_date: '01/12/2014', second_date: '02/12/2015' , expected_result: 12 },
129
+ { first_date: '02/03/2015', second_date: '01/03/2015' , expected_result: nil },
130
+ { first_date: '01/02/2015', second_date: '01/02/2015' , expected_result: nil } ]
131
+
132
+ context 'based on the above inputs' do
133
+ cases.each do |ymd|
134
+ it 'the result is #{ymd[:expected_result]}' do
135
+ expect( DateManager.new( ymd[:first_date], ymd[:second_date], 'DMY' ).months_between_dates ).to eq(ymd[:expected_result])
136
+ end
137
+ end
138
+ end
139
+
140
+ end
141
+
142
+ describe '#years_between_dates' do
143
+
144
+ cases = [ { first_date: '01/02/2015', second_date: '01/03/2015' , expected_result: 0 },
145
+ { first_date: '01/02/2015', second_date: '02/02/2015' , expected_result: 0 },
146
+ { first_date: '01/12/2014', second_date: '02/12/2015' , expected_result: 1 },
147
+ { first_date: '02/03/2015', second_date: '01/03/2015' , expected_result: nil },
148
+ { first_date: '01/02/2015', second_date: '01/02/2015' , expected_result: nil } ]
149
+
150
+ context 'based on the above inputs' do
151
+ cases.each do |ymd|
152
+ it 'the result is #{ymd[:expected_result]}' do
153
+ expect( DateManager.new( ymd[:first_date], ymd[:second_date], 'DMY' ).years_between_dates ).to eq(ymd[:expected_result])
154
+ end
155
+ end
156
+ end
157
+
158
+ end
159
+
160
+ describe '#differences_between_dates' do
161
+
162
+ context 'with start date "01/02/2015" and finish date 01/03/2015' do
163
+ it 'returns an array like {years: 0, months: 1, days: 28}' do
164
+ expect( DateManager.new( '01/02/2015', '01/03/2015', 'DMY' ).differences_between_dates ).to eq({years: 0, months: 1, days: 28})
165
+ end
166
+ end
167
+
168
+ context 'with start date "01/12/2014" and finish date 02/12/2015' do
169
+ it 'returns an array like {years: 1, months: 12, days: 366}' do
170
+ expect( DateManager.new( '01/12/2014', '02/12/2015', 'DMY' ).differences_between_dates ).to eq({years: 1, months: 12, days: 366})
171
+ end
172
+ end
173
+
174
+ end
175
+
176
+ describe '#start_date_leap_year?' do
177
+ context 'with start date "01/12/2016" and finish date 02/12/2020' do
178
+ it 'returns true - 2016 is a leap year' do
179
+ expect( DateManager.new( '01/12/2016', '02/12/2020', 'DMY' ).start_date_leap_year? ).to be true
180
+ end
181
+
182
+ it 'returns false - 2015 is not a leap year' do
183
+ expect( DateManager.new( '01/12/2015', '02/12/2020', 'DMY' ).start_date_leap_year? ).to be false
184
+ end
185
+ end
186
+ end
187
+
188
+ describe '#start_date_leap_year?' do
189
+ context 'with start date "01/12/2016" and finish date 02/12/2020' do
190
+ it 'returns true - 2020 is a leap year' do
191
+ expect( DateManager.new( '01/12/2015', '02/12/2020', 'DMY' ).finish_date_leap_year? ).to be true
192
+ end
193
+
194
+ it 'returns false - 2015 is not a leap year' do
195
+ expect( DateManager.new( '01/12/2015', '02/12/2015', 'DMY' ).finish_date_leap_year? ).to be false
196
+ end
197
+ end
198
+ end
199
+
200
+ describe '#human_readable_format' do
201
+ context 'with start date "01/12/2016" and finish date 02/12/2020' do
202
+ it 'returns -> "Date range between February 02, 2012 Thursday and February 03, 2012 Friday" ' do
203
+ expected_string = "First date : February 02, 2012 Thursday - Second date : February 03, 2012 Friday"
204
+ expect( DateManager.new( '2012/02/02', '2012/02/03' ).human_readable_format ).to eq(expected_string)
205
+ end
206
+ end
207
+ end
208
+
209
+ describe '#readable_days_between_dates' do
210
+ context 'with start date "2012/02/02" and finish date 2012/02/03' do
211
+ it 'returns -> "2 days" ' do
212
+ expected_string = "2 days"
213
+ expect( DateManager.new( '2012/02/01', '2012/02/03' ).readable_days_between_dates ).to eq(expected_string)
214
+ end
215
+ end
216
+ end
217
+
218
+ describe '#readable_months_between_dates' do
219
+ context 'with start date "2012/02/02" and finish date 2012/02/03' do
220
+ it 'returns -> "0 months" ' do
221
+ expected_string = "0 months"
222
+ expect( DateManager.new( '2012/02/01', '2012/02/03' ).readable_months_between_dates ).to eq(expected_string)
223
+ end
224
+ end
225
+ end
226
+
227
+ describe '#working_days' do
228
+ context 'with start date "2015/02/01" and finish date 2015/02/03' do
229
+ it 'returns 2 - First date is sunday and second tuesday' do
230
+ expect( DateManager.new( '2015/02/01', '2015/02/03' ).working_days ).to eq(2)
231
+ end
232
+ end
233
+
234
+ context 'with start date "2015/02/02" and finish date 2015/02/16' do
235
+ it 'returns 11 - First date is monday and second monday two weeks after' do
236
+ expect( DateManager.new( '2015/02/02', '2015/02/16' ).working_days ).to eq(11)
237
+ end
238
+ end
239
+
240
+ context 'with start date "2015/02/04" and finish date 2015/02/05' do
241
+ it 'returns 0 - First date is saturday and second sunday' do
242
+ expect( DateManager.new( '2015/04/04', '2015/04/05' ).working_days ).to eq(0)
243
+ end
244
+ end
245
+
246
+ end
247
+
248
+ describe '#total_weekend_days' do
249
+
250
+ cases = [ { first_date: '2015/02/02', second_date: '2015/02/05' , expected_result: 0 },
251
+ { first_date: '2015/02/01', second_date: '2015/02/03' , expected_result: 1 },
252
+ { first_date: '2015/01/30', second_date: '2015/02/13' , expected_result: 4 },
253
+ { first_date: '2015/01/30', second_date: '2015/02/20' , expected_result: 6 }]
254
+
255
+ context 'context based on the above inputs' do
256
+ cases.each do |ymd|
257
+ it 'the result is #{ymd[:expected_result]}' do
258
+ expect( DateManager.new( ymd[:first_date], ymd[:second_date] ).total_weekend_days ).to eq(ymd[:expected_result])
259
+ end
260
+ end
261
+ end
262
+
263
+ end
264
+ end
@@ -0,0 +1,144 @@
1
+ require 'date_manager'
2
+
3
+ describe DateParser do
4
+
5
+ describe '#initialize' do
6
+
7
+ context 'with a valid date_format given' do
8
+
9
+ DateParser::DATE_FORMAT.each do |format|
10
+ it '#{format} gets set' do
11
+ expect( DateParser.new('', '', format).format ).to eq(format)
12
+ end
13
+
14
+ it '#{format} gets set if it is in a lowercase' do
15
+ expect( DateParser.new('', '', format.downcase).format ).to eq(format)
16
+ end
17
+
18
+ end
19
+ end
20
+
21
+ context 'with a wrong date_format given' do
22
+
23
+ context 'if date_format is not present' do
24
+ it 'is set to YMD' do
25
+ expect( DateParser.new('', '').format ).to eq('YMD')
26
+ end
27
+ end
28
+
29
+ context 'if date_format is empty' do
30
+ it 'is set to YMD' do
31
+ expect( DateParser.new('', '', '').format ).to eq('YMD')
32
+ end
33
+ end
34
+
35
+ context 'if date_format is nil' do
36
+ it 'is set to YMD' do
37
+ expect( DateParser.new('', '', '').format ).to eq('YMD')
38
+ end
39
+ end
40
+
41
+ context 'if date_format given is not correct' do
42
+ it 'is set to nil' do
43
+ expect( DateParser.new('', '', 'whatever').format ).to eq(nil)
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
51
+ describe '#parse' do
52
+
53
+ context 'with a valid start date and finish date' do
54
+ context 'and a wrong date_format given' do
55
+ it 'returns nil' do
56
+ expect( DateParser.new( '02/03/2015', '03/03/2015', nil).parse ).to eq(nil)
57
+ end
58
+ end
59
+
60
+ context 'and valid YMD dates' do
61
+
62
+ context 'with valid params given' do
63
+ ymd_cases = [ { first_date: '2012/02/02', second_date: '2012/02/03' , format: 'YMD', date_structure: '%Y/%m/%d' },
64
+ { first_date: '2012.02.02', second_date: '2012.02.03' , format: 'YMD', date_structure: '%Y/%m/%d' },
65
+ { first_date: '2012-02-02', second_date: '2012-02-03' , format: 'YMD', date_structure: '%Y/%m/%d' } ]
66
+
67
+ ymd_cases.each do |ymd|
68
+
69
+ let(:result_objects_array) { [ DateTime.parse( ymd[:first_date], ymd[:date_structure]), DateTime.parse( ymd[:second_date], ymd[:date_structure]) ] }
70
+
71
+ it 'returns 2 Date objects for YMD format' do
72
+ expect( DateParser.new( ymd[:first_date], ymd[:second_date], ymd[:format]).parse ).to eq(result_objects_array )
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'and valid MDY dates' do
79
+
80
+ context 'with valid params given' do
81
+ mdy_cases = [ { first_date: '01/02/2015', second_date: '01/03/2015' , format: 'MDY', date_structure: '%m/%d/%Y' },
82
+ { first_date: '01.02.2015', second_date: '01.03.2015' , format: 'MDY', date_structure: '%m/%d/%Y' },
83
+ { first_date: '01-02-2015', second_date: '01-03-2015' , format: 'MDY', date_structure: '%m/%d/%Y' } ]
84
+
85
+ mdy_cases.each do |mdy|
86
+
87
+ let(:result_objects_array) { [ DateTime.parse( mdy[:first_date], mdy[:date_structure]), DateTime.parse( mdy[:second_date], mdy[:date_structure]) ] }
88
+
89
+ it 'returns 2 Date objects for YMD format' do
90
+ expect( DateParser.new( mdy[:first_date], mdy[:second_date], mdy[:format]).parse ).to eq(result_objects_array )
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ context 'and valid DMY dates' do
97
+
98
+ context 'with valid params given' do
99
+ dmy_cases = [ { first_date: '01/03/2015', second_date: '02/03/2015' , format: 'DMY', date_structure: '%d/%m/%Y' },
100
+ { first_date: '01.03.2015', second_date: '02.03.2015' , format: 'DMY', date_structure: '%d/%m/%Y' },
101
+ { first_date: '01-03-2015', second_date: '02-03-2015' , format: 'DMY', date_structure: '%d/%m/%Y' } ]
102
+
103
+ dmy_cases.each do |dmy|
104
+
105
+ let(:result_objects_array) { [ DateTime.parse( dmy[:first_date], dmy[:date_structure]), DateTime.parse( dmy[:second_date], dmy[:date_structure]) ] }
106
+
107
+ it 'returns 2 Date objects for YMD format' do
108
+ expect( DateParser.new( dmy[:first_date], dmy[:second_date], dmy[:format]).parse ).to eq(result_objects_array )
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ context 'when the format of the dates is not correct' do
116
+ context 'with no valid params given' do
117
+ dmy_cases = [ { first_date: '99/03/2015', second_date: '02/03/2015' , format: 'DMY', date_structure: '%d/%m/%Y' },
118
+ { first_date: '01.13.2015', second_date: '42.03.2015' , format: 'DMY', date_structure: '%d/%m/%Y' },
119
+ { first_date: '00-03-2015', second_date: '02-19-2015' , format: 'DMY', date_structure: '%d/%m/%Y' } ]
120
+
121
+ dmy_cases.each do |dmy|
122
+ it 'returns an ArgumentError - invalid date' do
123
+ expect{ DateParser.new( dmy[:first_date], dmy[:second_date], dmy[:format]).parse }.to raise_error(ArgumentError)
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ context 'when the format of the dates does not belong to the structured format' do
130
+ dmy_cases = [ { first_date: '01/03/2015', second_date: '02/03/2015' , format: 'YMD', date_structure: '%d/%m/%Y' },
131
+ { first_date: '31.03.2015', second_date: '31.12.2015' , format: '' , date_structure: '%d/%m/%Y' },
132
+ { first_date: '2012-03-02', second_date: '2012-03-04' , format: 'DMY', date_structure: '%d/%m/%Y' } ]
133
+
134
+ dmy_cases.each do |dmy|
135
+ it 'returns an ArgumentError - invalid date' do
136
+ expect( DateParser.new( dmy[:first_date], dmy[:second_date], dmy[:format]).parse ).to be_nil
137
+ end
138
+ end
139
+
140
+ end
141
+
142
+ end
143
+
144
+ end
@@ -0,0 +1,48 @@
1
+ require 'date_manager'
2
+
3
+ describe HumanReadableParser do
4
+
5
+ subject { DateManager.new( '2012/02/01', '2012/02/03' ) }
6
+
7
+ describe '.to_human_readable_date' do
8
+ context "giving two DateTime object" do
9
+ it "should return an human readable string containing date, month and year" do
10
+ expected_string = "First date : February 01, 2012 Wednesday - Second date : February 03, 2012 Friday"
11
+ expect(HumanReadableParser.to_human_readable_date(subject.start_date, subject.finish_date)).to eq(expected_string)
12
+ end
13
+ end
14
+
15
+ end
16
+
17
+ describe '.days_between_dates' do
18
+ context "giving two DateTime object" do
19
+ it "should return an human readable string containing the days in between" do
20
+ expected_string = "2 days"
21
+ expect(HumanReadableParser.days_between_dates(subject.days_between_dates)).to eq(expected_string)
22
+ end
23
+ end
24
+
25
+ context "giving two DateTime object and a language" do
26
+ it "should return an human readable string containing the days in between translated to spanish" do
27
+ expected_string = "2 dias"
28
+ expect(HumanReadableParser.days_between_dates(subject.days_between_dates, 'es')).to eq(expected_string)
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '.months_between_dates' do
34
+ context "giving two DateTime object" do
35
+ it "should return an human readable string containing the months in between" do
36
+ expected_string = "0 months"
37
+ expect(HumanReadableParser.months_between_dates(subject.months_between_dates)).to eq(expected_string)
38
+ end
39
+ end
40
+
41
+ context "giving two DateTime object and a language" do
42
+ it "should return an human readable string containing the months in between" do
43
+ expected_string = "0 meses"
44
+ expect(HumanReadableParser.months_between_dates(subject.months_between_dates, 'es')).to eq(expected_string)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1 @@
1
+ require 'date_manager'
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: date_manager
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Fernando
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-11-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Parse, validate, manipulate, and display dates.
63
+ email:
64
+ - fgonzalezaguilera@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - date_manager.gemspec
75
+ - lib/date_manager.rb
76
+ - lib/date_manager/date_parser.rb
77
+ - lib/date_manager/human_readable_parser.rb
78
+ - lib/date_manager/version.rb
79
+ - lib/translations/translation.yml
80
+ - spec/date_manager_spec.rb
81
+ - spec/date_parser_spec.rb
82
+ - spec/human_readable_parser_spec.rb
83
+ - spec/spec_helper.rb
84
+ homepage: ''
85
+ licenses:
86
+ - MIT
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 1.8.23
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: ''
109
+ test_files:
110
+ - spec/date_manager_spec.rb
111
+ - spec/date_parser_spec.rb
112
+ - spec/human_readable_parser_spec.rb
113
+ - spec/spec_helper.rb