human_date_range 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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