Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

it works

  • Loading branch information...
commit 1c75a50cbc20997859db1c19da34d6c48df9b783 1 parent 892516c
@kristianmandrup authored
View
14 .gitignore
@@ -28,22 +28,22 @@ pkg
#
# For MacOS:
#
-#.DS_Store
+.DS_Store
# For TextMate
-#*.tmproj
-#tmtags
+*.tmproj
+tmtags
# For emacs:
#*~
-#\#*
-#.\#*
+\#*
+.\#*
# For vim:
-#*.swp
+*.swp
# For redcar:
-#.redcar
+.redcar
# For rubinius:
#*.rbc
View
2  Gemfile
@@ -7,6 +7,8 @@ gem 'ruby-duration', :git => 'git://github.com/kristianmandrup/ruby-duration.git
group :test, :development do
gem "rspec", ">= 2.8.0"
+ gem 'rails', '~> 3.2'
+ # gem 'i18n'
end
group :development do
View
68 Gemfile.lock
@@ -9,23 +9,80 @@ GIT
GEM
remote: http://rubygems.org/
specs:
+ actionmailer (3.2.3)
+ actionpack (= 3.2.3)
+ mail (~> 2.4.4)
+ actionpack (3.2.3)
+ activemodel (= 3.2.3)
+ activesupport (= 3.2.3)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ journey (~> 1.0.1)
+ rack (~> 1.4.0)
+ rack-cache (~> 1.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.1.2)
+ activemodel (3.2.3)
+ activesupport (= 3.2.3)
+ builder (~> 3.0.0)
+ activerecord (3.2.3)
+ activemodel (= 3.2.3)
+ activesupport (= 3.2.3)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activeresource (3.2.3)
+ activemodel (= 3.2.3)
+ activesupport (= 3.2.3)
activesupport (3.2.3)
i18n (~> 0.6)
multi_json (~> 1.0)
+ arel (3.0.2)
+ builder (3.0.0)
chronic (0.6.7)
chronic_duration (0.9.6)
numerizer (~> 0.1.1)
diff-lcs (1.1.3)
+ erubis (2.7.0)
git (1.2.5)
+ hike (1.2.1)
i18n (0.6.0)
jeweler (1.8.3)
bundler (~> 1.0)
git (>= 1.2.5)
rake
rdoc
+ journey (1.0.3)
json (1.6.6)
+ mail (2.4.4)
+ i18n (>= 0.4.0)
+ mime-types (~> 1.16)
+ treetop (~> 1.4.8)
+ mime-types (1.18)
multi_json (1.3.2)
numerizer (0.1.1)
+ polyglot (0.3.3)
+ rack (1.4.1)
+ rack-cache (1.2)
+ rack (>= 0.4)
+ rack-ssl (1.3.2)
+ rack
+ rack-test (0.6.1)
+ rack (>= 1.0)
+ rails (3.2.3)
+ actionmailer (= 3.2.3)
+ actionpack (= 3.2.3)
+ activerecord (= 3.2.3)
+ activeresource (= 3.2.3)
+ activesupport (= 3.2.3)
+ bundler (~> 1.0)
+ railties (= 3.2.3)
+ railties (3.2.3)
+ actionpack (= 3.2.3)
+ activesupport (= 3.2.3)
+ rack-ssl (~> 1.3.2)
+ rake (>= 0.8.7)
+ rdoc (~> 3.4)
+ thor (~> 0.14.6)
rake (0.9.2.2)
rdoc (3.12)
json (~> 1.4)
@@ -42,6 +99,16 @@ GEM
simplecov-html (~> 0.5.3)
simplecov-html (0.5.3)
spanner (0.0.2)
+ sprockets (2.1.2)
+ hike (~> 1.2)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ thor (0.14.6)
+ tilt (1.3.3)
+ treetop (1.4.10)
+ polyglot
+ polyglot (>= 0.3.1)
+ tzinfo (0.3.33)
PLATFORMS
ruby
@@ -51,6 +118,7 @@ DEPENDENCIES
chronic
chronic_duration
jeweler (>= 1.8.3)
+ rails (~> 3.2)
rdoc (>= 3.12)
rspec (>= 2.8.0)
ruby-duration!
View
77 README.md
@@ -2,7 +2,7 @@
Use Timespans in Ruby :)
-Will calculate time diff in milliseconds between to dates, then allow you to get the time difference in some time unit as a number.
+Will calculate time diff between two dates, then allow you to get the time difference in some time unit as a number.
```ruby
t = Timespan.new(:start => Date.today, :duration => 3.days.ago)
@@ -11,6 +11,10 @@ Will calculate time diff in milliseconds between to dates, then allow you to get
t.to_secs # => 259200
t.to_hours = 10800
+ t = Timespan.new("2 days") # from today
+
+ t = Timespan.new("3 hrs").from(2.days.from_now)
+
t = Timespan.new(:from => Date.today, :to => "6 weeks from now")
t = Timespan.new(:from => Date.today, :duration => "7 weeks 3 days")
@@ -19,13 +23,10 @@ Will calculate time diff in milliseconds between to dates, then allow you to get
See specs for more examples of usage
-## TODO
-
-* use Duration for duration calculations!
-* Calculate start_time and end_time based on duration if not set explicitly!
-
## Spanner
+Internally Timespan uses Spanner to parse duration strings.
+
`Spanner.parse('23 hours 12 minutes')
## Duration (ruby-duration)
@@ -41,20 +42,25 @@ Duration.new(:weeks => 1, :days => 20).format("%w %~w and %d %~d") => "3 weeks a
Duration locale file
```yaml
-pt:
+da:
ruby_duration:
- second: segundo
- seconds: segundos
- minute: minuto
- minutes: minutos
- hour: hora
- hours: horas
- day: dia
- days: dias
- week: semana
- weeks: semanas
+ second: sekond
+ seconds: sekonder
+ minute: minut
+ minutes: minutter
+ hour: time
+ hours: timer
+ day: dag
+ days: dage
+ week: uge
+ weeks: uges
+ month: måned
+ months: måneder
+ year: år
+ years: år
```
+Duration datatype for Mongoid
```ruby
require 'duration/mongoid'
@@ -63,13 +69,46 @@ class MyModel
include Mongoid::Document
field :duration, type => Duration
end
-``
+```
+
+## Timespan i18n
+
+Timespan locale file
+
+```yaml
+da:
+ timespan:
+ from: fra
+ to: til
+ lasting: der varer ialt
+```
+
+## Timespan for Mongoid
+
+Custom Timespan datatype
+
+```ruby
+require 'timespan/mongoid'
+
+class MyModel
+ include Mongoid::Document
+ field :period, type => Timespan
+end
+```
## Chronic duration
+Is used to parse duration strings if Spanner can't be handle it
+
`ChronicDuration.parse('4 minutes and 30 seconds')
-## Days and times
+### Endure
+
+Use the 'endure' gem based on the old "days_and_times".
+
+See: [days_and_times](https://github.com/kristianmandrup/days_and_times)
+
+Currently it also uses Duration, which conflicts with the 'ruby-duration' gem.
```
1.day #=> A duration of 1 day
View
5 config/locales/timespan/da.yml
@@ -0,0 +1,5 @@
+da:
+ timespan:
+ from: fra
+ to: til
+ lasting: der varer ialt
View
42 lib/timespan.rb
@@ -8,6 +8,9 @@
require 'timespan/printer'
require 'timespan/span'
+if defined?(Rails) && Rails::VERSION::STRING.to >= '3.1'
+ require 'duration/rails/engine'
+end
class Timespan
include Span
@@ -22,9 +25,20 @@ class TimeParseError < StandardError; end
alias_method :start_date, :start_time
alias_method :end_date, :end_time
+ START_KEYS = [:start, :from]
+ END_KEYS = [:to, :end]
+ DURATION_KEYS = [:duration, :lasting]
+
+ ALL_KEYS = START_KEYS + END_KEYS + DURATION_KEYS
+
def initialize options = {}
@is_new = true
+ case options
+ when Numeric, Duration, String
+ options = {:duration => options}
+ end
+
configure options
@is_new = false
@@ -39,6 +53,11 @@ def start_time= time
end
end
alias_method :start_date=, :start_time=
+
+ def from time
+ self.start_time = time
+ self
+ end
def end_time= time
@end_time = convert_to_time time
@@ -50,6 +69,11 @@ def end_time= time
end
alias_method :end_date=, :end_time=
+ def until time
+ self.end_time = time
+ self
+ end
+
def convert_to_time time
case time
when String
@@ -65,19 +89,31 @@ def convert_to_time time
protected
+ def first_from keys, options = {}
+ keys.select {|key| options[key] }.first
+ end
+
def configure options = {}
- from = options[:from] || options[:start]
- to = options[:to] || options[:end]
+ from = options[first_from START_KEYS, options]
+ to = options[first_from END_KEYS, options]
+ dur = options[first_from DURATION_KEYS, options]
- self.duration = options[:duration] if options[:duration]
+ self.duration = dur if dur
self.start_time = from if from
self.end_time = to if to
+
+ default_from_now! unless start_time || end_time
+
calculate_miss!
rescue Exception => e
calculate_miss!
validate!
end
+ def default_from_now!
+ self.start_time = Time.now
+ end
+
def validate!
raise ArgumentError, "#{valid_requirement}, was: #{current_config}" unless valid?
end
View
31 lib/timespan/mongoid.rb
@@ -0,0 +1,31 @@
+require "timespan"
+require "mongoid/fields"
+
+# Mongoid serialization support for Timespan type.
+module Mongoid
+ module Fields
+ class Timespan
+ include Mongoid::Fields::Serializable
+
+ # Deserialize a Timespan given the hash stored by Mongodb
+ #
+ # @param [Hash] Timespan as hash
+ # @return [Timespan] deserialized Timespan
+ def deserialize(timespan_hash)
+ return if !timespan_hash
+ ::Timespan.new(:from => timespan_hash[:from], :to => timespan_hash[:to])
+ end
+
+ # Serialize a Timespan or a Hash (with Timespan units) or a Duration in some form to
+ # a BSON serializable type.
+ #
+ # @param [Timespan, Hash, Integer, String] value
+ # @return [Hash] Timespan in seconds
+ def serialize(value)
+ return if value.blank?
+ timespan = ::Timespan.new(value)
+ {:from => time_span.start_time, :to => time_span.end_time, :Timespan => time_span.Timespan}
+ end
+ end
+ end
+end
View
2  lib/timespan/printer.rb
@@ -1,3 +1,5 @@
+require 'i18n'
+
class Timespan
class << self
attr_writer :time_format
View
9 lib/timespan/rails/engine.rb
@@ -0,0 +1,9 @@
+module Timespan
+ module Rails
+ class Engine < ::Rails::Engine
+ initializer 'Timespan setup' do
+ I18n.load_path << Dir[Rails.root.join('config', 'locales', 'timespan', '*.yml')]
+ end
+ end
+ end
+end
View
21 spec/timespan_spec.rb
@@ -6,6 +6,27 @@
let(:from) { Chronic.parse("1 day ago") }
let(:to) { Time.now }
+ context '2 days duration (from now - default)' do
+ let(:timespan) { Timespan.new :duration => "2 days"}
+
+ describe '.start_date' do
+ it 'should default to today' do
+ DateTime.parse(subject.start_date.to_s).strftime('%d %b %Y').should == Date.today.strftime('%d %b %Y')
+ end
+ end
+ end
+
+ context '3 hrs duration from now 2 days from now' do
+ let(:timespan) { Timespan.new("3 hrs").from(2.days.from_now) }
+
+ describe '.start_date' do
+ its(:start_date) { should be }
+ its(:end_date) { should be }
+ its(:duration) { should be_a Duration }
+ end
+ end
+
+
context 'From and To with 1 day apart' do
let(:timespan) { Timespan.new :from => from, :to => to}
Please sign in to comment.
Something went wrong with that request. Please try again.