Permalink
Browse files

readme and sundry files

  • Loading branch information...
adzap committed Oct 14, 2010
1 parent 3fd8569 commit 312eaf7f6e4531cb6004e19cfbd9501e240c72c2
Showing with 326 additions and 0 deletions.
  1. 0 CHANGELOG.rdoc
  2. +20 −0 LICENSE
  3. +242 −0 README.rdoc
  4. +64 −0 Rakefile
View
No changes.
View
20 LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2010 Adam Meehan
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
@@ -0,0 +1,242 @@
+= Timeliness
+
+* Source: http://github.com/adzap/timeliness
+* Bugs: http://github.com/adzap/timeliness/issues
+
+== Description
+
+Date/time parser for Ruby with the following features:
+
+* Extensible with custom formats and tokens.
+* It's pretty fast. Up to 60% faster than Time/Date parse method.
+* Control the parser strictness.
+* Control behaviour of ambiguous date formats (US vs European e.g. mm/dd/yy, dd/mm/yy).
+* I18n support (for months).
+* Fewer WTFs than Time/Date parse method.
+* Has no dependencies.
+
+Extracted from the validates_timeliness gem, it has been rewritten cleaner and much faster. It's most suitable for when
+you need to control the parsing behaviour. It's faster than the Time/Date class parse methods, so it has general appeal.
+
+
+== Usage
+
+The simplest example is just a straight forward string parse:
+
+ Timeliness.parse('2010-09-08 12:13:14') #=> Wed Sep 08 12:13:14 1000 2010
+ Timeliness.parse('2010-09-08') #=> Wed Sep 08 00:00:00 1000 2010
+ Timeliness.parse('12:13:14') #=> Sat Jan 01 12:13:14 1100 2000
+
+Notice a time only string will return with a date value. The date value can be configured globally with
+this setting:
+
+ Timeliness.date_for_time_type = [2010, 1, 1]
+
+or specified with :now option:
+
+ Timeliness.parse('12:13:14', :now => Time.mktime(2010,9,8)) #=> Wed Sep 08 12:13:14 1000 2010
+
+You can also provide a type which will tell the parser that you are only interested in the values for that type.
+
+ Timeliness.parse('2010-09-08 12:13:14', :date) #=> Wed Sep 08 00:00:00 1000 2010
+ Timeliness.parse('2010-09-08 12:13:14', :time) #=> Sat Jan 01 12:13:14 1100 2000
+ Timeliness.parse('2010-09-08 12:13:14', :datetime) #=> Wed Sep 08 12:13:14 1000 2010 i.e. the whole string is used
+
+Now let's get strict. Pass the :strict option with true and things get finicky
+
+ Timeliness.parse('2010-09-08 12:13:14', :date, :strict => true) #=> nil
+ Timeliness.parse('2010-09-08 12:13:14', :time, :strict => true) #=> nil
+ Timeliness.parse('2010-09-08 12:13:14', :datetime, :strict => true) #=> Wed Sep 08 12:13:14 1000 2010 i.e. the whole string is used
+
+The strict option without a type is ignored.
+
+To control what zone the time object is returned in, you have two options. Firstly you can set the default zone. Below
+is the list of options with their effective time creation method call
+
+ Timeliness.default_timezone = :local # Time.local(...)
+ Timeliness.default_timezone = :utc # Time.utc(...)
+ Timeliness.default_timezone = :current # Time.zone.local(...)
+ Timeliness.default_timezone = 'Melbourne' # Time.use_zone('Melbourne') { Time.zone.local(...) }
+
+The last two options require that you have ActiveSupport timezone extension loaded.
+
+You can also use the :zone option to control it for a single parse call:
+
+ Timeliness.parse('2010-09-08 12:13:14', :zone => :utc) #=> Wed Sep 08 12:13:14 UTC 2010
+ Timeliness.parse('2010-09-08 12:13:14', :zone => :local) #=> Wed Sep 08 12:13:14 1000 2010
+ Timeliness.parse('2010-09-08 12:13:14', :zone => :current) #=> Wed Sep 08 12:13:14 1000 2010, with Time.zone = 'Melbourne'
+ Timeliness.parse('2010-09-08 12:13:14', :zone => 'Melbourne') #=> Wed Sep 08 12:13:14 1000 2010
+
+Remember, you must have ActiveSupport timezone extension loaded to use the last two examples.
+
+To get super finicky, you can restrict the parsing to a single format with the :format option
+
+ Timeliness.parse('2010-09-08 12:13:14', :format => 'yyyy-mm-dd hh:nn:ss') #=> Wed Sep 08 12:13:14 UTC 2010
+ Timeliness.parse('08/09/2010 12:13:14', :format => 'yyyy-mm-dd hh:nn:ss') #=> nil
+
+If you would like to get the raw array of values before the time object is created, you can with
+
+ Timeliness._parse('2010-09-08 12:13:14') # => [2010, 9, 8, 12, 13, 14, nil]
+
+The last nil is for the empty value of microseconds.
+
+
+== Formats
+
+The gem has default formats included which can be easily added to using the format syntax. Also formats can be easily
+removed so that they are no longer considered valid.
+
+Below are the default formats. If you think they are easy to read then you will be happy to know that is exactly the same
+format syntax you can use to define your own. No complex regular expressions are needed.
+
+
+=== Datetime formats
+
+ m/d/yy h:nn:ss OR d/m/yy hh:nn:ss
+ m/d/yy h:nn OR d/m/yy h:nn
+ m/d/yy h:nn_ampm OR d/m/yy h:nn_ampm
+ yyyy-mm-dd hh:nn:ss
+ yyyy-mm-dd h:nn
+ ddd mmm d hh:nn:ss zo yyyy # Ruby time string
+ yyyy-mm-ddThh:nn:ssZ # ISO 8601 without zone offset
+ yyyy-mm-ddThh:nn:sszo # ISO 8601 with zone offset
+
+NOTE: To use non-US date formats see US/Euro Formats section
+
+
+=== Date formats
+
+ yyyy/mm/dd
+ yyyy-mm-dd
+ yyyy.mm.dd
+ m/d/yy OR d/m/yy
+ m\d\yy OR d\m\yy
+ d-m-yy
+ dd-mm-yyyy
+ d.m.yy
+ d mmm yy
+
+NOTE: To use non-US date formats see US/Euro Formats section
+
+
+=== Time formats
+
+ hh:nn:ss
+ hh-nn-ss
+ h:nn
+ h.nn
+ h nn
+ h-nn
+ h:nn_ampm
+ h.nn_ampm
+ h nn_ampm
+ h-nn_ampm
+ h_ampm
+
+NOTE: Any time format without a meridian token (the 'ampm' token) is considered in 24 hour time.
+
+
+=== Format Tokens
+
+Here is what each format token means:
+
+ Format tokens:
+ y = year
+ m = month
+ d = day
+ h = hour
+ n = minute
+ s = second
+ u = micro-seconds
+ ampm = meridian (am or pm) with or without dots (e.g. am, a.m, or a.m.)
+ _ = optional space
+ tz = Timezone abbreviation (e.g. UTC, GMT, PST, EST)
+ zo = Timezone offset (e.g. +10:00, -08:00, +1000)
+
+ Repeating tokens:
+ x = 1 or 2 digits for unit (e.g. 'h' means an hour can be '9' or '09')
+ xx = 2 digits exactly for unit (e.g. 'hh' means an hour can only be '09')
+
+ Special Cases:
+ yy = 2 or 4 digit year
+ yyyy = exactly 4 digit year
+ mmm = month long name (e.g. 'Jul' or 'July')
+ ddd = Day name of 3 to 9 letters (e.g. Wed or Wednesday)
+ u = microseconds matches 1 to 3 digits
+
+All other characters are considered literal. For the technically minded, these formats are compiled into a single regular expression
+
+To see all defined formats look at the {parser source code}[http://github.com/adzap/timeliness/tree/master/lib/timeliness/parser.rb].
+
+
+== Settings
+
+=== US/Euro Formats
+
+The perennial problem for non-US developers or applications not primarily for the
+US, is the US date format of m/d/yy. This is ambiguous with the European format
+of d/m/yy. By default the gem uses the US formats as this is the Ruby default
+when it does date interpretation.
+
+To switch to using the European (or Rest of The World) formats use this setting
+
+ Timeliness.use_euro_formats
+
+Now '01/02/2000' will be parsed as 1st February 2000, instead of 2nd January 2000.
+
+You can switch back to US formats with
+
+ Timeliness.use_us_formats
+
+
+=== Customising Formats
+
+Sometimes you may not want certain formats to be valid. You can remove formats for each type and
+the parser will then not consider that a valid format. To remove a format
+
+ Timeliness.remove_formats(:date, 'm\d\yy')
+
+Adding new formats is also simple
+
+ Timeliness.add_formats(:time, "d o'clock")
+
+Now "10 o'clock" will be a valid value.
+
+You can embed regular expressions in the format but no guarantees that it will
+remain intact. If you avoid the use of any token characters, and regexp dots or
+backslashes as special characters in the regexp, it may work as expected.
+For special characters use POSIX character classes for safety. See the ISO 8601
+datetime for an example of an embedded regular expression.
+
+Because formats are evaluated in order, adding a format which may be ambiguous
+with an existing format, will mean your format is ignored. If you need to make
+your new format higher precedence than an existing format, you can include the
+before option like so
+
+ Timeliness.add_formats(:time, 'ss:nn:hh', :before => 'hh:nn:ss')
+
+Now a time of '59:30:23' will be interpreted as 11:30:59 pm. This option saves
+you adding a new one and deleting an old one to get it to work.
+
+
+=== Ambiguous Year
+
+When dealing with 2 digit year values, by default a year is interpreted as being
+in the last century when at or above 30. You can customize this however
+
+ Timeliness.ambiguous_year_threshold = 20
+
+Now you get:
+
+ year of 19 is considered 2019
+ year of 20 is considered 1920
+
+
+== Credits
+
+* Adam Meehan (adam.meehan@gmail.com, http://github.com/adzap)
+
+
+== License
+
+Copyright (c) 2010 Adam Meehan, released under the MIT license
View
@@ -0,0 +1,64 @@
+require 'rubygems'
+require 'rake/rdoctask'
+require 'rake/gempackagetask'
+require 'rubygems/specification'
+require 'rspec/core/rake_task'
+require 'lib/timeliness/version'
+
+GEM_NAME = "timeliness"
+GEM_VERSION = Timeliness::VERSION
+
+spec = Gem::Specification.new do |s|
+ s.name = GEM_NAME
+ s.version = GEM_VERSION
+ s.platform = Gem::Platform::RUBY
+ s.rubyforge_project = "timeliness"
+ s.has_rdoc = true
+ s.extra_rdoc_files = ["README.rdoc", "CHANGELOG.rdoc"]
+ s.summary = %q{Fast date and time parser with customisable formats and I18n support.}
+ s.description = s.summary
+ s.author = "Adam Meehan"
+ s.email = "adam.meehan@gmail.com"
+ s.homepage = "http://github.com/adzap/timeliness"
+ s.require_path = 'lib'
+ s.files = %w(timeliness.gemspec LICENSE CHANGELOG.rdoc README.rdoc Rakefile) + Dir.glob("{lib,spec}/**/*")
+end
+
+desc 'Default: run specs.'
+task :default => :spec
+
+desc "Run specs"
+RSpec::Core::RakeTask.new do |t|
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
+end
+
+desc "Generate code coverage"
+RSpec::Core::RakeTask.new(:coverage) do |t|
+ t.rcov = true
+ t.rcov_opts = ['--exclude', 'spec']
+end
+
+desc 'Generate documentation for plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'Timeliness'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+Rake::GemPackageTask.new(spec) do |pkg|
+ pkg.gem_spec = spec
+end
+
+desc "Install the gem locally"
+task :install => [:package] do
+ sh %{gem install pkg/#{GEM_NAME}-#{GEM_VERSION}}
+end
+
+desc "Create a gemspec file"
+task :make_spec do
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
+ file.puts spec.to_ruby
+ end
+end

0 comments on commit 312eaf7

Please sign in to comment.