human_date_range 0.0.1

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: ae034d1136599c52ad31343fd1a3c8d098c4fb3e
4
+ data.tar.gz: d7cf6cb33109a42f89de024dcc2c95997e7bc84e
5
+ SHA512:
6
+ metadata.gz: a4f42dffc4c4033eabfca618ab4532788f65043694f171cb57fd0f88d0e69812fc6a618989e4b59695760fbb67a04f227fa9385be5267b50594740f5740fad4e
7
+ data.tar.gz: dc20021b1e4cced3992a0bf318d6c2ab5a509a89595f74515d5123f3eb83386be254ffc1bdbd1641052093825e62432c90a053418499a6b0f71adc9b8b87a2bf
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,11 @@
1
+ require 'date'
2
+ require 'unicode'
3
+
4
+ require "human_date_range/version"
5
+ require "human_date_range/parser"
6
+
7
+ module HumanDateRange
8
+ def self.parse(string, language=:russian, format="%d-%m-%Y")
9
+ Parser.new(string, language, format).parse
10
+ end
11
+ end
@@ -0,0 +1,98 @@
1
+ module HumanDateRange
2
+ class Parser
3
+ # Порядок имеет значение
4
+ NORMALIZERS = {
5
+ russian: {
6
+ /(января|январь|янв\.?|янвр\.?)/ => 'Jan',
7
+ /(ферваль|февраля|фев\.?|февр\.?)/ => 'Feb',
8
+ /(марта|март|мар\.?|март\.?)/ => 'Mar',
9
+ /(апрель|апреля|апр\.?)/ => 'Apr',
10
+ /(май|мая|май\.?)/ => 'May',
11
+ /(июнь|июня|июн\.?)/ => 'Jun',
12
+ /(июль|июля|июл\.?)/ => 'Jul',
13
+ /(августа|август|авг\.?)/ => 'Aug',
14
+ /(сентябрь|сентября|сен\.?)/ => 'Sep',
15
+ /(октябрь|октября|окт\.?)/ => 'Oct',
16
+ /(ноябрь|ноября|ноя\.?)/ => 'Nov',
17
+ /(декабрь|декабря|дек\.?)/ => 'Dec',
18
+ /((в )?(\d\d\:\d\d))/ => '',
19
+ /\s(год|года)\s/ => '',
20
+ /\s(пнд|втр|срд|чтв|птц|сбт|вск)/ => '',
21
+ /\s(пн|вт|ср|чт|пт|сб|вс)/ => '',
22
+ /сегодня/ => -> { Date.today.strftime("%d-%m-%Y") }.call ,
23
+ /послезавтра/ => -> { ( Date.today + 2 ).strftime("%d-%m-%Y") }.call ,
24
+ /завтра/ => -> { ( Date.today + 1 ).strftime("%d-%m-%Y") }.call ,
25
+ /вчера/ => -> { ( Date.today - 1 ).strftime("%d-%m-%Y") }.call ,
26
+ /с(?:о)?(.+)по(.+)/ => '\1 - \2',
27
+ /\s+/ => ' ',
28
+ /[,|-]\s?+\z/ => '',
29
+ /(года|год|г)/ => ''
30
+ }
31
+ }
32
+ MONTHES_REGEXP = %w[jan feb mar apr may jun jul aug sep oct nov dec].join('|')
33
+
34
+ def initialize(string, language=:russian, output_format="%d-%m-%Y")
35
+ raise ArgumentError unless string.kind_of?(String)
36
+ @string = string
37
+ @language = language
38
+ @output_format = output_format
39
+ end
40
+
41
+ def parse
42
+ normalize!
43
+ begin
44
+ perform(@string)
45
+ rescue ArgumentError
46
+ nil
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def normalize!
53
+ @string = Unicode.downcase(@string).strip
54
+ NORMALIZERS[@language].each{ |k,v| @string.gsub!(k,v) }
55
+ @string.strip
56
+ @string = @string.split(',') if @string =~ /,/
57
+ end
58
+
59
+ # Здесь основная логика для специфичных случаев
60
+ def perform( string )
61
+ if string.kind_of?(Array)
62
+ dates = []
63
+ string.each{ |date| dates << perform(date) }
64
+ dates.flatten.compact
65
+ else
66
+ case
67
+ when string.match(/\A(\d{1,2}\.\d{1,2})\z/)
68
+ # дд.мм
69
+ # 12.03
70
+ Date.parse("#{$1}.2015").strftime(@output_format)
71
+ when string.match( /\A(\d{1,2})\s?+-\s?+(\d{1,2}) (#{MONTHES_REGEXP})\s?+(201[456])?\z/ )
72
+ # дд-дд (мм) гг
73
+ # 12-31 декабря 2015
74
+ starts = Date.parse("#$1 #$3 #$4")
75
+ ends = Date.parse("#$2 #$3 #$4")
76
+ parse_range(starts, ends)
77
+ when string.match( /(.*) - (.*)/ )
78
+ # Дата - Дата
79
+ # 1 декабря - 13 февраля 2016
80
+ starts = Date.parse(perform("#$1"))
81
+ ends = Date.parse(perform("#$2"))
82
+ parse_range(starts, ends)
83
+ else
84
+ Date.parse(string).strftime(@output_format)
85
+ end
86
+ end
87
+ end
88
+
89
+ def parse_range( start_date, end_date )
90
+ # Предполагаем, что дата начала указана для прошлого года,
91
+ # если начало позже окончания.
92
+ # Например, с 12 декабря по 1 февраля
93
+ start_date = start_date - 1.year if start_date > end_date
94
+ (start_date..end_date).to_a.map{ |d| d.strftime(@output_format) }
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,3 @@
1
+ module HumanDateRange
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ describe HumanDateRange do
3
+ before(:all) do
4
+ @format = "%d-%m-%Y"
5
+ @language = :russian
6
+ @dates = {
7
+ russian: {
8
+ "сегодня" => Date.today.strftime(@format),
9
+ "завтра" => ( Date.today + 1 ).strftime(@format),
10
+ "С 1 мая по 3 мая" => [ "01-05-2015", "02-05-2015", "03-05-2015"]
11
+ }
12
+ }
13
+ end
14
+
15
+ it "parses required formats" do
16
+ @dates[@language].each do |date,expected|
17
+ expect(HumanDateRange.parse(date)).to eq expected
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ require 'bundler/setup'
2
+
3
+ Bundler.setup
4
+
5
+ require 'human_date_range'
6
+
7
+ RSpec.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: human_date_range
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - ablebeam
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: unicode
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
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: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description: ''
70
+ email:
71
+ - victor@ablebeam.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - Rakefile
77
+ - lib/human_date_range.rb
78
+ - lib/human_date_range/parser.rb
79
+ - lib/human_date_range/version.rb
80
+ - spec/human_date_range_spec.rb
81
+ - spec/spec_helper.rb
82
+ homepage: https://github.com/ablebeam/human_date_range
83
+ licenses:
84
+ - MIT
85
+ metadata: {}
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 2.4.5
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: "Парсер человеческих дат и диапазонов для русского языка."
106
+ test_files:
107
+ - spec/human_date_range_spec.rb
108
+ - spec/spec_helper.rb