Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Or install it yourself as:

## Usage

### .parse

Simple. Very similiar with `Date.parse`. Just:
```ruby
['invalid', 'monday', '01-01-2019'].each do |date|
Expand All @@ -36,6 +38,27 @@ If your date is valid, then will return your valid date.
If your date is not valid, then will return your alternate.
Simple, right?

### .smart_change

```ruby
Dalt.smart_change('31-12-2019', month: 2)
```

```
=> 29 February 2019
```

You can even use alternet in `.smart_change`

```ruby
Dalt.smart_change('31-12-2019', month: 2, alt: 'Alternate date')
```

```
=> "Alternate date"
```


## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/whatdacode/dalt. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
Expand Down
9 changes: 7 additions & 2 deletions lib/dalt.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
require 'date'
require 'dalt/error/without_alternate'
require 'dalt/formatter'
require 'dalt/parser'
require 'dalt/version'

# Dalt will use instance of Dalt::Parser
module Dalt
def self.parse(text, alt: nil)
@date = Dalt::Parser.new(text, alt: alt).parse
def self.parse(date, alt: nil)
@date = Dalt::Parser.new(date.to_s, alt: alt).parse
end

def self.smart_change(date, options)
Dalt::Formatter.new(date.to_s, options).smart_change
end
end
75 changes: 75 additions & 0 deletions lib/dalt/formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
module Dalt
# This class will handle all of date formatting
class Formatter
def initialize(date, options = {})
@date = Date.parse(date.to_s)
@options = options
end

def smart_change
Parser.new(date_after_changed.to_s, alt: @options.fetch(:alt, smart_changing)).parse
end

private

def date_after_changed
return Date.civil year, month, -1 if end_of_month?

Date.new year, month, day
rescue ArgumentError
nil
end

def day
@day ||= @options.fetch(:day, @date.day)
end

def end_of_month
Date.civil year, month, -1
end

def end_of_month?
@date.month != @date.next_day.month
end

def month
@month ||= @options.fetch(:month, @date.month)
end

def month_changed?
@options.fetch(:month, false)
end

# Automatically assigned to max posibility of changes
# Note: Order matter
def smart_changing
return smart_month_changing if month_changed?

# means the only day will be change,
# so we can just return max posibility of day which is end of month
end_of_month
end

def smart_month_changing
# When month is out of range, we automatically assign it to max poisibility of month,
# which is december || 12
new_date = if month > 12
Date.new year, 12
else
Date.new year, month
end

new_end_of_month = Date.civil(new_date.year, new_date.month, -1)

# its double check for day. If after we changed the day and day is out of range,
# then we automatically assign it to max posibility of day which is end of month
return new_end_of_month if new_end_of_month.day < day

Date.new new_date.year, new_date.month, day
end

def year
@year ||= @options.fetch(:year, @date.year)
end
end
end
81 changes: 81 additions & 0 deletions spec/dalt/formatter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
RSpec.describe Dalt::Formatter do
describe '#smart_change' do
let(:changer) { described_class.new(date, options) }

context 'changing the month' do
let(:date) { Date.parse('31-01-2019') }

context 'change end of the month' do
let(:options) { { month: 2 } }
it 'returns end of the month of selected month' do
expect(changer.smart_change).to eql Date.parse('28-02-2019')
end
end

context 'out of range month' do
context 'have alternate options' do
let(:options) { { month: 13, alt: 'Alternate date' } }
it 'returns alternate' do
expect(changer.smart_change).to eql 'Alternate date'
end
end

context 'have no alternate options' do
let(:options) { { month: 13 } }

it 'return max month' do
expect(changer.smart_change).to eq Date.parse('31-12-2019')
end
end
end
end

context 'changing the day' do
let(:date) { Date.parse('01-02-2019') }

context 'day is out of range' do
context 'have alternate options' do
let(:options) { { day: 31, alt: 'Alternate date' } }
it 'returns alternate' do
expect(changer.smart_change).to eql 'Alternate date'
end
end

context 'have no alternate options' do
let(:options) { { day: 31 } }

it 'return last date on that month' do
expect(changer.smart_change).to eq Date.parse('28-02-2019')
end
end
end

context 'day is in range' do
let(:options) { { day: 20, alt: 'Alternate date' } }
it 'returns the new date' do
expect(changer.smart_change).to eq Date.parse('20-02-2019')
end
end
end

context 'change both day and month' do
let(:date) { Date.parse('01-02-2019') }

context 'both is out of range' do
context 'have alternate' do
let(:options) { { day: 32, month: 13, year: 2020, alt: 'Alternate date' } }
it 'return the alternate' do
expect(changer.smart_change).to eq 'Alternate date'
end
end

context 'have no alternate' do
let(:options) { { day: 32, month: 13, year: 2020 } }
it 'return max posibility of day and month' do
expect(changer.smart_change).to eq Date.parse('31-12-2020')
end
end
end
end
end
end
32 changes: 26 additions & 6 deletions spec/dalt_spec.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
RSpec.describe Dalt do
it 'return date if valid' do
parse = described_class.parse('monday', alt: 'Hello')
expect(parse).to eq(Date.parse('monday'))
describe '.parse' do
it 'return date if valid' do
parse = described_class.parse('monday', alt: 'Hello')
expect(parse).to eq(Date.parse('monday'))
end

it 'return alternate if invalid' do
parse = described_class.parse('invalid', alt: 'Hello')
expect(parse).to eq('Hello')
end
end

it 'return alternate if invalid' do
parse = described_class.parse('invalid', alt: 'Hello')
expect(parse).to eq('Hello')
describe '.smart_change' do
it 'returns date if no alternate' do
format = described_class.smart_change('31-01-2012', day: 32, month: 31, year: 2020)

expect(format).to eq Date.parse '31-12-2020'
end

it 'returns alternet if alternate exist' do
format = described_class.smart_change('31-01-2012',
day: 32,
month: 31,
year: 2020,
alt: 'Alternate date')

expect(format).to eq 'Alternate date'
end
end
end