formatter-date 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9a1d1b7ed3503913cbdf6b9b495f683639888cbb
4
+ data.tar.gz: a0a7c966c14714e23ed248c0766e9bf1c10d6a2a
5
+ SHA512:
6
+ metadata.gz: e8ceec176d6c5da892ee830537a32adc056cc739c947f695624b05fcf80b69f224d5ebc8814ee99733a085cba135735653eb1d34461364af917cd1a1a31a0df6
7
+ data.tar.gz: 4b6f9973a336b95739816e897479efbbe69cac118b76228b8c863d529a64da892663f2b66b5794d35263efd5a4a18d30ff58e3db386fb76d6616c5fa826ffaf2
data/.gitignore ADDED
@@ -0,0 +1,22 @@
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
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rubocop.yml ADDED
@@ -0,0 +1,77 @@
1
+ AllCops:
2
+ Exclude:
3
+ - Gemfile
4
+ - bin/**/*
5
+ - vendor/**/*
6
+
7
+ Encoding:
8
+ Enabled: true
9
+
10
+ Documentation:
11
+ Enabled: true
12
+ Exclude:
13
+ - test/**/*
14
+
15
+ LineLength:
16
+ Max: 80
17
+
18
+ # Class
19
+ ClassLength:
20
+ Max: 80
21
+
22
+ EmptyLinesAroundAccessModifier:
23
+ Enabled: false
24
+
25
+ AccessModifierIndentation:
26
+ EnforcedStyle: indent
27
+
28
+ # Error
29
+ RaiseArgs:
30
+ EnforcedStyle: exploded
31
+
32
+ SignalException:
33
+ EnforcedStyle: semantic
34
+
35
+ # Method
36
+ MethodLength:
37
+ Max: 10
38
+
39
+ SingleLineMethods:
40
+ AllowIfMethodIsEmpty: false
41
+
42
+ CollectionMethods:
43
+ PreferredMethods:
44
+ collect: 'map'
45
+ collect!: 'map!'
46
+ reduce: 'inject'
47
+ detect: 'find'
48
+ find_all: 'select'
49
+
50
+ # Parameter
51
+ ParameterLists:
52
+ Max: 3
53
+ CountKeywordArgs: true
54
+
55
+ BracesAroundHashParameters:
56
+ Enabled: false
57
+ EnforcedStyle: braces
58
+
59
+ # Block
60
+ BlockNesting:
61
+ Max: 3
62
+
63
+ # Brackets
64
+ SpaceInsideBrackets:
65
+ Enabled: true
66
+
67
+ # Hash
68
+ IndentHash:
69
+ EnforcedStyle: consistent
70
+
71
+ SpaceInsideHashLiteralBraces:
72
+ EnforcedStyle: space
73
+ EnforcedStyleForEmptyBraces: space
74
+
75
+ # String
76
+ StringLiterals:
77
+ EnforcedStyle: single_quotes
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ script: 'bundle exec rake ci'
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.2
7
+ - jruby-19mode
8
+ - rbx-2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in formatter-date.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Terje Larsen
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # formatter-date
2
+
3
+ Format Time/DateTime with time zone offset
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/formatter-date.svg)](http://badge.fury.io/rb/formatter-date)
6
+ [![Build
7
+ Status](https://travis-ci.org/terlar/formatter-date.svg)](https://travis-ci.org/terlar/formatter-date)
8
+ [![Code Climate](https://codeclimate.com/github/terlar/formatter-date.png)](https://codeclimate.com/github/terlar/formatter-date)
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'formatter-date'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install formatter-date
23
+
24
+ ## Usage
25
+
26
+ ```ruby
27
+ # By default it will use the ISO8601 formatting.
28
+ formatter = Formatter::Date.new('Asia/Karachi')
29
+ formatter.format(Time.now) # "2015-02-22T03:48:07+05:00"
30
+
31
+ # Available formats iso8601, xmlschema, jisx0301, rfc3339
32
+ formatter = Formatter::Date.new('Asia/Karachi', :jisx0301)
33
+ formatter.format(Time.now) # "H27.02.22T03:48:07+05:00"
34
+
35
+ # You can also provide fractional seconds to be used with formats
36
+ formatter = Formatter::Date.new('Asia/Karachi', :iso8601, 2)
37
+ formatter.format(Time.now) # 2015-02-22T03:48:07.46+05:00
38
+
39
+ # Provide a custom string formatting (delegates to strftime)
40
+ formatter = Formatter::Date.new('Asia/Karachi', '%FT%T%:z')
41
+ formatter.format(Time.now) # "2015-02-22T03:48:07+05:00"
42
+
43
+ # Get configured time zone identifier
44
+ formatter.identifier # "Asia/Karachi"
45
+
46
+ # Get configured time zone offset
47
+ formatter.offset # (5/24)
48
+ ```
49
+
50
+ ## Contributing
51
+
52
+ 1. Fork it ( https://github.com/terlar/formatter-date/fork )
53
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
54
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
55
+ 4. Push to the branch (`git push origin my-new-feature`)
56
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ require 'bundler/setup'
4
+ require 'bundler/gem_tasks'
5
+
6
+ require 'rake/testtask'
7
+ require 'rubocop/rake_task'
8
+
9
+ RuboCop::RakeTask.new
10
+
11
+ task default: :test
12
+ task test: 'test:all'
13
+ task ci: %w(rubocop test:all)
14
+
15
+ namespace :test do
16
+ desc 'Run all tests'
17
+ Rake::TestTask.new :all do |t|
18
+ t.test_files = Rake::FileList['test/*_test.rb']
19
+ end
20
+
21
+ desc 'Run unit tests'
22
+ Rake::TestTask.new :unit do |t|
23
+ t.test_files = Rake::FileList['test/unit_test.rb']
24
+ end
25
+
26
+ desc 'Run integration tests'
27
+ Rake::TestTask.new :integration do |t|
28
+ t.test_files = Rake::FileList['test/integration_test.rb']
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../lib/formatter/date/version', __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = 'formatter-date'
7
+ gem.version = Formatter::Date::VERSION.dup
8
+ gem.authors = ['Terje Larsen']
9
+ gem.email = 'terlar@gmail.com'
10
+ gem.description = 'Date formatter with time zone support'
11
+ gem.summary = gem.description
12
+ gem.homepage = 'https://github.com/terlar/formatter-date'
13
+ gem.license = 'MIT'
14
+
15
+ gem.require_paths = %w(lib)
16
+ gem.files = `git ls-files`.split($RS)
17
+ gem.test_files = gem.files.grep(/^test\//)
18
+ gem.extra_rdoc_files = %w(LICENSE README.md)
19
+
20
+ gem.required_ruby_version = '>= 1.9.3'
21
+
22
+ gem.add_runtime_dependency 'tzinfo'
23
+
24
+ gem.add_development_dependency 'bundler', '~> 1.6'
25
+ gem.add_development_dependency 'rake'
26
+ gem.add_development_dependency 'minitest'
27
+ gem.add_development_dependency 'rubocop'
28
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ module Formatter
4
+ class Date
5
+
6
+ # Gem version
7
+ VERSION = '0.1.0'
8
+
9
+ end
10
+ end
@@ -0,0 +1,114 @@
1
+ # encoding: utf-8
2
+
3
+ require 'tzinfo'
4
+ require 'delegate'
5
+
6
+ module Formatter
7
+ # Date formatter with time zone support.
8
+ class Date
9
+ # Wrapper class around TZInfo::TimeOrDateTime that only accepts
10
+ # Time or DateTime.
11
+ class TimeOrDateTime < DelegateClass(TZInfo::TimeOrDateTime)
12
+ def initialize(object)
13
+ case object
14
+ when Time
15
+ object = object.utc
16
+ when DateTime
17
+ object = object.new_offset Rational(0, 24)
18
+ else
19
+ fail ArgumentError, "invalid Time or DateTime: #{object.inspect}"
20
+ end
21
+
22
+ super TZInfo::TimeOrDateTime.wrap(object)
23
+ end
24
+ end
25
+
26
+ # Initialize a formatter with the desired options.
27
+ #
28
+ # :time_zone specifies which time zone to use when formatting.
29
+ #
30
+ # :format specifies which format to use, it can either be a symbol of a
31
+ # predefined format or a string with a custom format which will be
32
+ # delegated to DateTime#strftime.
33
+ #
34
+ # :fraction is length of fractional seconds to be used with predefined
35
+ # formats.
36
+ #
37
+ # @param [String|TZInfo::Timezone] time_zone
38
+ # @param [Symbol|String] format
39
+ # @param [Integer] fraction (0)
40
+ #
41
+ # @return [undefined]
42
+ #
43
+ # @api public
44
+ def initialize(time_zone, format = :iso8601, fraction = 0)
45
+ self.time_zone = time_zone
46
+ @formatter = formatter_for format, fraction
47
+ end
48
+
49
+ # Format Time or DateTime with formatter
50
+ #
51
+ # @param [Time|DateTime] time_or_datetime
52
+ #
53
+ # @return [String]
54
+ #
55
+ # @api public
56
+ def format(time_or_datetime)
57
+ formatter.call with_offset(time_or_datetime)
58
+ end
59
+
60
+ # Configured time zone identifier
61
+ #
62
+ # @return [String]
63
+ #
64
+ # @api public
65
+ def identifier
66
+ time_zone.identifier
67
+ end
68
+
69
+ # Configured time zone offset
70
+ #
71
+ # @return [Rational]
72
+ #
73
+ # @api public
74
+ def offset
75
+ time_zone.current_period.utc_total_offset_rational
76
+ end
77
+
78
+ private
79
+
80
+ attr_reader :time_zone, :formatter
81
+
82
+ def time_zone=(time_zone)
83
+ case time_zone
84
+ when String
85
+ @time_zone = TZInfo::Timezone.get time_zone
86
+ when TZInfo::DataTimezone
87
+ @time_zone = time_zone
88
+ else
89
+ fail ArgumentError, "invalid time zone: #{time_zone.inspect}"
90
+ end
91
+ end
92
+
93
+ def formatter_for(format, fraction)
94
+ case format
95
+ when Symbol
96
+ if format_method? format
97
+ return -> datetime { datetime.send format, fraction }
98
+ end
99
+ when String
100
+ return -> datetime { datetime.strftime format }
101
+ end
102
+
103
+ fail ArgumentError, "invalid value for format: #{format.inspect}"
104
+ end
105
+
106
+ def format_method?(method)
107
+ %i(iso8601 xmlschema jisx0301 rfc3339).include? method
108
+ end
109
+
110
+ def with_offset(time_or_datetime)
111
+ TimeOrDateTime.new(time_or_datetime).to_datetime.new_offset offset
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+
3
+ require 'formatter/date'
@@ -0,0 +1,128 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'test_helper'
4
+
5
+ class IntegrationTest < Minitest::Test
6
+ attr_reader :time_zone, :format
7
+
8
+ def setup
9
+ @time_zone = 'Europe/Stockholm'
10
+ @format = :iso8601
11
+ end
12
+
13
+ def formatter
14
+ Formatter::Date.new time_zone, format
15
+ end
16
+
17
+ def test_can_initialize_with_string
18
+ @time_zone = 'Asia/Karachi'
19
+ assert_equal 'Asia/Karachi', formatter.identifier
20
+ end
21
+
22
+ def test_can_initialize_with_tzinfo_timezone
23
+ @time_zone = TZInfo::Timezone.get('Asia/Karachi')
24
+ assert_equal 'Asia/Karachi', formatter.identifier
25
+ end
26
+
27
+ def test_fails_initialization_with_invalid_time_zone
28
+ @time_zone = nil
29
+
30
+ error = assert_raises ArgumentError do
31
+ formatter
32
+ end
33
+
34
+ assert_includes error.message, 'nil'
35
+ end
36
+
37
+ def test_fails_initialization_with_invalid_format
38
+ @format = :unknown
39
+
40
+ error = assert_raises ArgumentError do
41
+ formatter
42
+ end
43
+ assert_includes error.message, ':unknown'
44
+
45
+ @format = 5
46
+ error = assert_raises ArgumentError do
47
+ formatter
48
+ end
49
+ assert_includes error.message, '5'
50
+ end
51
+
52
+ def test_identifier
53
+ assert_equal time_zone, formatter.identifier
54
+ end
55
+
56
+ def test_offset
57
+ assert_equal Rational(1, 24), formatter.offset
58
+ end
59
+
60
+ def test_formats_time_with_offset
61
+ input = Time.new(2010, 1, 1, 10, 0, 0, '+00:00')
62
+
63
+ expected = '2010-01-01T11:00:00+01:00'
64
+ actual = formatter.format input
65
+
66
+ assert_equal expected, actual
67
+ end
68
+
69
+ def test_formats_datetime_with_offset
70
+ input = DateTime.new(2010, 1, 1, 10, 0, 0, Rational(0, 24))
71
+
72
+ expected = '2010-01-01T11:00:00+01:00'
73
+ actual = formatter.format input
74
+
75
+ assert_equal expected, actual
76
+ end
77
+
78
+ def test_defaults_format_to_iso8601
79
+ formatter = Formatter::Date.new time_zone
80
+ input = Time.new(2010, 1, 1, 10, 0, 0, '+00:00')
81
+
82
+ expected = '2010-01-01T11:00:00+01:00'
83
+ actual = formatter.format input
84
+
85
+ assert_equal expected, actual
86
+ end
87
+
88
+ def test_format_with_fractional_seconds
89
+ formatter = Formatter::Date.new time_zone, :iso8601, 2
90
+ input = Time.new(2010, 1, 1, 10, 0, 0, '+00:00')
91
+
92
+ expected = '2010-01-01T11:00:00.00+01:00'
93
+ actual = formatter.format input
94
+
95
+ assert_equal expected, actual
96
+ end
97
+
98
+ def test_format_with_custom_string
99
+ @format = '%Y%m%dT%H%M%S%z'
100
+ input = Time.new(2010, 1, 1, 10, 0, 0, '+00:00')
101
+
102
+ expected = '20100101T110000+0100'
103
+ actual = formatter.format input
104
+
105
+ assert_equal expected, actual
106
+ end
107
+
108
+ %w(iso8601 xmlschema jisx0301 rfc3339).each do |format|
109
+ define_method :"test_format_with_#{format}" do
110
+ @format = format.to_sym
111
+
112
+ input = DateTime.new(2010, 1, 1, 10, 0, 0, formatter.offset)
113
+
114
+ expected = input.send(format)
115
+ actual = formatter.format input
116
+
117
+ assert_equal expected, actual
118
+ end
119
+ end
120
+
121
+ def test_fails_formatting_with_invalid_time
122
+ error = assert_raises ArgumentError do
123
+ formatter.format('invalid time')
124
+ end
125
+
126
+ assert_includes error.message, '"invalid time"'
127
+ end
128
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ require 'bundler/setup'
4
+ require 'formatter-date'
5
+ require 'minitest/autorun'
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: formatter-date
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Terje Larsen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tzinfo
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
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: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Date formatter with time zone support
84
+ email: terlar@gmail.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files:
88
+ - LICENSE
89
+ - README.md
90
+ files:
91
+ - ".gitignore"
92
+ - ".rubocop.yml"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - LICENSE
96
+ - README.md
97
+ - Rakefile
98
+ - formatter-date.gemspec
99
+ - lib/formatter-date.rb
100
+ - lib/formatter/date.rb
101
+ - lib/formatter/date/version.rb
102
+ - test/integration_test.rb
103
+ - test/test_helper.rb
104
+ homepage: https://github.com/terlar/formatter-date
105
+ licenses:
106
+ - MIT
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 1.9.3
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 2.2.2
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: Date formatter with time zone support
128
+ test_files:
129
+ - test/integration_test.rb
130
+ - test/test_helper.rb