├── .gitignore ├── .rspec ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── dates_from_string.gemspec ├── lib ├── dates_from_string.rb └── dates_from_string │ ├── parsing_structure.rb │ ├── patterns.rb │ └── version.rb └── spec ├── dates_from_string_spec.rb └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.6.3 4 | before_install: gem install bundler -v 2.0 5 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 4 | 5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion. 6 | 7 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 8 | 9 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. 10 | 11 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 12 | 13 | This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/) 14 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in dates_from_string.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Sergey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Gem](https://img.shields.io/gem/v/dates_from_string.svg?style=flat-square)](https://rubygems.org/gems/dates_from_string) 2 | [![Build Status](https://travis-ci.org/sergey-chechaev/dates_from_string.svg?branch=master)](https://travis-ci.org/sergey-chechaev/dates_from_string) 3 | # DatesFromString 4 | 5 | Flexible solution for finding dates in text. After parsing text, the gem return flexible structure of dates, that allow getting a date by you own logic use distance for next date type and keywords between dates. Gem also support find a year in email and find a date in structure. 6 | 7 | 8 | ## Installation 9 | 10 | Add this line to your application's Gemfile: 11 | 12 | ```ruby 13 | gem 'dates_from_string' 14 | ``` 15 | 16 | And then execute: 17 | 18 | $ bundle 19 | 20 | Or install it yourself as: 21 | 22 | $ gem install dates_from_string 23 | 24 | ## Usage 25 | 26 | 27 | ```ruby 28 | text = "1988-1990 and 2000 and one more date 04.04.2015" # parsing text 29 | key_words = ['between','-'] # you can define special separator 30 | options = { 31 | date_format: :usa, # year,day,month by default year,month,day 32 | ordinals: ['nd', 'st', 'th'] # a string list that might accompany a day, default none 33 | } 34 | dates_from_string = DatesFromString.new(key_words, options) # define DatesFromString object 35 | dates_from_string.get_structure(text) # parsing text 36 | 37 | #=> returns 38 | # [{:type=>:year, :value=>"1988", :distance=>0, :key_words=>["-"]}, 39 | # {:type=>:year, :value=>"1990", :distance=>2, :key_words=>[]}, 40 | # {:type=>:year, :value=>"2000", :distance=>5, :key_words=>[]}, 41 | # {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 42 | # {:type=>:day, :value=>"04", :distance=>0, :key_words=>[]}, 43 | # {:type=>:month, :value=>"04", :distance=>0, :key_words=>[]}] 44 | 45 | :type # type of date year, month or day 46 | :value # value of date 47 | :distance # distance for next date type 48 | :key_words # special words, symbols that separate dates 49 | 50 | # find date in structure 51 | text = "забрать машину из ремонта 2015-02-02 23:00:10" 52 | dates_from_string = DatesFromString.new 53 | dates_from_string.find_date(text) 54 | 55 | #=> return 56 | # ["2015-02-02 23:00:10"] 57 | 58 | 59 | # find year in email 60 | date_from_string = DatesFromString.new() 61 | input = '1test1988@gmail.com' 62 | date_from_string.email_date(input) 63 | #=> return 64 | # "1988" 65 | ``` 66 | 67 | 68 | 69 | 70 | 71 | Examples: 72 | 73 | ```ruby 74 | input = '1988 between 1990' 75 | key_words = ['between'] 76 | dates_from_string = DatesFromString.new(key_words) 77 | dates_from_string.get_structure(input) 78 | 79 | #=> return 80 | # [{:type=>:year, :value=>"1988", :distance=>2, :key_words=>["between"]}, 81 | # {:type=>:year, :value=>"1990", :distance=>0, :key_words=>[]}] 82 | 83 | input = '2013/07/09 one date and he born in 1990' 84 | dates_from_string.get_structure(input) 85 | 86 | #=> return 87 | # [{:type=>:year, :value=>"2013", :distance=>0, :key_words=>[]}, 88 | # {:type=>:month, :value=>"07", :distance=>0, :key_words=>[]}, 89 | # {:type=>:day, :value=>"09", :distance=>7, :key_words=>[]}, 90 | # {:type=>:year, :value=>"1990", :distance=>0, :key_words=>[]}] 91 | 92 | input = '1990 1988 year 2013 bla bla bla 2015 a b c d i f g qwe 2016' 93 | dates_from_string.get_structure(input) 94 | 95 | #=> return 96 | # [{:type=>:year, :value=>"1990", :distance=>1, :key_words=>[]}, 97 | # {:type=>:year, :value=>"1988", :distance=>2, :key_words=>[]}, 98 | # {:type=>:year, :value=>"2013", :distance=>4, :key_words=>[]}, 99 | # {:type=>:year, :value=>"2015", :distance=>9, :key_words=>[]}, 100 | # {:type=>:year, :value=>"2016", :distance=>0, :key_words=>[]}] 101 | 102 | input = 'August 1961' 103 | dates_from_string.get_structure(input) 104 | 105 | #=> return 106 | # [{:type=>:month, :value=>"08", :distance=>1, :key_words=>[]}, 107 | # {:type=>:year, :value=>"1961", :distance=>0, :key_words=>[]}] 108 | 109 | input = '10 April 1948' 110 | dates_from_string.get_structure(input) 111 | 112 | #=> return 113 | # [{:type=>:day, :value=>"10", :distance=>1, :key_words=>[]}, 114 | # {:type=>:month, :value=>"04", :distance=>1, :key_words=>[]}, 115 | # {:type=>:year, :value=>"1948", :distance=>0, :key_words=>[]}] 116 | # 117 | 118 | input = 'circa 1960 and full date 07 Jun 1941' 119 | dates_from_string.get_structure(input) 120 | 121 | #=> return 122 | # [{:type=>:year, :value=>"1960", :distance=>4, :key_words=>[]}, 123 | # {:type=>:day, :value=>"07", :distance=>1, :key_words=>[]}, 124 | # {:type=>:month, :value=>"06", :distance=>1, :key_words=>[]}, 125 | # {:type=>:year, :value=>"1941", :distance=>0, :key_words=>[]}] 126 | 127 | obj = DatesFromString.new(['and']) 128 | input = 'between 1960 and 1965' 129 | obj.get_structure(input) 130 | 131 | #=> return 132 | # [{:type=>:year, :value=>"1960", :distance=>2, :key_words=>['and']}, 133 | # {:type=>:year, :value=>"1965", :distance=>0, :key_words=>[]},] 134 | 135 | dates_from_string_with_ordinals = DatesFromString.new(['and'], ordinals: ['st', 'th', 'nd']) 136 | input = 'around September 2nd, 2013' 137 | dates_from_string_with_ordinals.get_structure(input) 138 | 139 | #=> return 140 | # [{:type=>:month, :value=>"09", :distance=>1, :key_words=>[]}, 141 | # {:type=>:day, :value=>"2", :distance=>1, :key_words=>[]}, 142 | # {:type=>:year, :value=>"2013", :distance=>0, :key_words=>[]}] 143 | 144 | input = "In September 2011, following a change in the law extending 145 | the presidential term from four years to six,[5] Putin announced 146 | that he would seek a third, non-consecutive term as President in 147 | the 2012 presidential election, an announcement which led to 148 | large-scale protests in many Russian cities. In March 2012 he won the election, 149 | which was criticized for procedural irregularities, and is serving a six-year term" 150 | dates_from_string.get_structure(input) 151 | 152 | #=> return 153 | # [{:type=>:month, :value=>"09", :distance=>1, :key_words=>[]}, 154 | # {:type=>:year, :value=>"2011", :distance=>30, :key_words=>[]}, 155 | # {:type=>:year, :value=>"2012", :distance=>15, :key_words=>[]}, 156 | # {:type=>:month, :value=>"03", :distance=>1, :key_words=>[]}, 157 | # {:type=>:year, :value=>"2012", :distance=>0, :key_words=>[]}] 158 | ``` 159 | 160 | ## Development 161 | 162 | After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment. 163 | 164 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 165 | 166 | ## Contributing 167 | 168 | 1. Fork it ( https://github.com/[my-github-username]/dates_from_string/fork ) 169 | 2. Create your feature branch (`git checkout -b my-new-feature`) 170 | 3. Commit your changes (`git commit -am 'Add some feature'`) 171 | 4. Push to the branch (`git push origin my-new-feature`) 172 | 5. Create a new Pull Request 173 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task :default => :spec 7 | 8 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "dates_from_string" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | 5 | bundle install 6 | 7 | # Do any other automated setup that you need to do here 8 | -------------------------------------------------------------------------------- /dates_from_string.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'dates_from_string/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "dates_from_string" 8 | spec.version = DatesFromString::VERSION 9 | spec.authors = ["Sergey Chechaev"] 10 | spec.email = ["kompotdrinker@gmail.com"] 11 | 12 | spec.summary = %q{Flexible solution for finding all formats of dates in text} 13 | spec.description = %q{Flexible solution for finding all formats of dates in text} 14 | spec.homepage = "" 15 | spec.license = "MIT" 16 | 17 | # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or 18 | # delete this section to allow pushing this gem to any host. 19 | # if spec.respond_to?(:metadata) 20 | # spec.metadata['allowed_push_host'] = "https://rubygems.org" 21 | # else 22 | # raise "RubyGems 2.0 or newer is required to protect against public gem pushes." 23 | # end 24 | 25 | spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } 26 | spec.bindir = "exe" 27 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 28 | spec.require_paths = ["lib"] 29 | # Only with ruby 2.0.x 30 | spec.required_ruby_version = '~> 2.0' 31 | 32 | spec.add_development_dependency "bundler", "~> 2.0" 33 | spec.add_development_dependency "rake", "~> 13.0" 34 | spec.add_development_dependency "rspec", "~> 3.9" 35 | 36 | 37 | spec.add_development_dependency 'pry-rails' 38 | end 39 | -------------------------------------------------------------------------------- /lib/dates_from_string.rb: -------------------------------------------------------------------------------- 1 | require 'dates_from_string/version' 2 | require 'dates_from_string/parsing_structure' 3 | require 'dates_from_string/patterns' 4 | 5 | class DatesFromString 6 | include Patterns 7 | 8 | def initialize(key_words = [], date_format: :default, ordinals: []) 9 | @key_words = key_words 10 | @date_format = date_format_by_country(date_format) 11 | @ordinals = Array(ordinals) 12 | end 13 | 14 | def find_date(string) 15 | parsing_structure = ParsingStructure.new(get_structure(string)) 16 | parsing_structure.start 17 | end 18 | 19 | def get_clear_text 20 | @clear_text.strip 21 | end 22 | 23 | def email_date(email) 24 | email.match(/(?:(?:19|20)[0-9]{2})/).to_s 25 | end 26 | 27 | def date_format_by_country(date_format) 28 | DATE_COUNTRY_FORMAT[date_format.to_sym].call 29 | end 30 | 31 | def day_regex 32 | @day_regex ||= begin 33 | if @ordinals.any? 34 | ordinal_regex = "(#{@ordinals.join('|')})?" 35 | /^\d{1,2}#{ordinal_regex},?$/ 36 | else 37 | /^\d{1,2},?$/ 38 | end 39 | end 40 | end 41 | 42 | def get_structure(string) 43 | unless string.nil? || string.empty? 44 | @main_arr = [] 45 | data_arr = string.split(" ") 46 | @indexs = [] 47 | @first_index = [] 48 | @clear_text = string.clone 49 | 50 | data_arr.each_with_index do |data, index| 51 | value_year = get_year(data) 52 | value_full_date = get_full_date(data) 53 | value_month_year_date = get_month_year_date(data) 54 | value_dash = get_dash_data(data) 55 | value_month = get_month_by_list(data) 56 | value_short_month = get_short_month(data) 57 | value_time = get_time(data) 58 | 59 | value_day = get_day(data) 60 | next_index = index + 1 61 | 62 | if value_year 63 | add_to_structure(:year ,value_year, index, next_index, data_arr) 64 | end 65 | 66 | if value_full_date 67 | if @main_arr.size == 0 68 | index = 0 69 | end 70 | add_to_structure(@date_format[0], value_full_date[0], index, next_index, data_arr) 71 | add_to_structure(@date_format[1], value_full_date[1], index, next_index, data_arr) 72 | add_to_structure(@date_format[2], value_full_date[2], index, next_index, data_arr) 73 | end 74 | 75 | if value_month_year_date 76 | add_to_structure(:year , value_month_year_date[0], index, next_index, data_arr) 77 | add_to_structure(:month ,value_month_year_date[1], index, next_index, data_arr) 78 | end 79 | 80 | if value_dash 81 | add_to_structure(:year ,value_dash[0], index, next_index, data_arr, '-') 82 | add_to_structure(:year ,value_dash[1], index, next_index, data_arr) 83 | end 84 | 85 | if value_month 86 | add_to_structure(:month ,value_month, index, next_index, data_arr) 87 | end 88 | 89 | if value_short_month 90 | add_to_structure(:month ,value_short_month, index, next_index, data_arr) 91 | end 92 | 93 | if value_day 94 | add_to_structure(:day ,value_day, index, next_index, data_arr) 95 | end 96 | 97 | if value_time 98 | add_to_structure(:time ,value_time, index, next_index, data_arr) 99 | end 100 | 101 | end 102 | 103 | return @main_arr 104 | else 105 | nil 106 | end 107 | end 108 | 109 | def get_time(string) 110 | if (result = string.match(/\d{2}:\d{2}:\d{2}/)) 111 | @clear_text.slice!(result.to_s) 112 | result.to_s 113 | elsif (result = string.match(/\d{2}:\d{2}/)) 114 | @clear_text.slice!(result.to_s) 115 | result.to_s 116 | else 117 | nil 118 | end 119 | end 120 | 121 | def get_year(string) 122 | if string =~ /^\d{4}$/ 123 | string 124 | elsif string =~ /^\d{4}\.$/ 125 | string.delete!('.') 126 | elsif string =~ /^\d{4}\,$/ 127 | string.delete!(',') 128 | else 129 | nil 130 | end 131 | end 132 | 133 | def get_full_date(string) 134 | PATTERNS.keys.each do |patterns| 135 | patterns.each do |pattern| 136 | if (result = string.match(pattern)) 137 | @clear_text.slice!(result.to_s) 138 | return PATTERNS[patterns].call result 139 | end 140 | end 141 | end 142 | 143 | nil 144 | end 145 | 146 | def get_month_year_date(string) 147 | if (result = string.match(/^\d{2}\.\d{4}$/)) 148 | result.to_s.split(".").reverse 149 | elsif (result = string.match(/^\d{4}\.\d{2}$/)) 150 | result.to_s.split(".") 151 | else 152 | nil 153 | end 154 | end 155 | 156 | def get_day(string) 157 | if string =~ (day_regex) 158 | string.gsub(Regexp.union(@ordinals + [',']), '') 159 | else 160 | nil 161 | end 162 | end 163 | 164 | 165 | def get_dash_data(string) 166 | if (result = string.match(/\d{4}-\d{4}/)) 167 | result.to_s.split("-") 168 | elsif (result = string.match(/\d{4}–\d{4}/)) 169 | result.to_s.split("–") 170 | else 171 | nil 172 | end 173 | end 174 | 175 | def get_month_by_list(string) 176 | month = ['January','February','March','April','May','June','July','August','September','October','November','December'] 177 | index = month.index(string.chomp(',')) 178 | 179 | if index 180 | sprintf('%02d',(index+1)) 181 | else 182 | nil 183 | end 184 | 185 | end 186 | 187 | def get_short_month(string) 188 | short_month = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] 189 | short_index = short_month.index(string.chomp(',')) 190 | 191 | if short_index 192 | sprintf('%02d',(short_index+1)) 193 | else 194 | nil 195 | end 196 | end 197 | 198 | def add_to_structure (type ,value, index, next_index, data_arr, key_word = nil) 199 | set_structura 200 | if value 201 | @first_index << index 202 | @structura[:type] = type 203 | @structura[:value] = value 204 | end 205 | 206 | if value && @main_arr.last 207 | @main_arr.last[:distance] = calc_index(index) 208 | end 209 | 210 | if @key_words && @key_words.include?(data_arr[next_index]) 211 | @structura[:key_words] << data_arr[next_index] 212 | end 213 | 214 | if key_word 215 | @structura[:key_words] << key_word 216 | end 217 | 218 | if value 219 | @main_arr << @structura 220 | value = nil 221 | end 222 | end 223 | 224 | def calc_index(index) 225 | result = nil 226 | @indexs << index 227 | if @indexs.count > 1 228 | result = (index - @indexs[-2]) 229 | elsif @first_index[0] < index 230 | result = (index - @first_index[0]) 231 | else 232 | result = index 233 | end 234 | end 235 | 236 | def set_structura 237 | @structura = {type: nil, value: nil, distance: 0, key_words: []} 238 | end 239 | end 240 | -------------------------------------------------------------------------------- /lib/dates_from_string/parsing_structure.rb: -------------------------------------------------------------------------------- 1 | require "dates_from_string/version" 2 | 3 | class ParsingStructure 4 | 5 | def initialize(structure) 6 | @structure = structure 7 | 8 | @array_of_full_data = [] 9 | end 10 | 11 | def start 12 | if @structure 13 | if (@structure.select {|father| father[:type] == :time }).any? 14 | get_year_month_day_time 15 | else 16 | get_year_month_day 17 | end 18 | end 19 | 20 | return @array_of_full_data 21 | end 22 | 23 | def get_year_month_day_time 24 | set_year_month_day_time 25 | 26 | if @structure 27 | @structure.each do |item| 28 | if item[:type] == :year 29 | @year = item[:value] 30 | end 31 | 32 | if item[:type] == :month 33 | @month = item[:value] 34 | end 35 | 36 | if item[:type] == :day 37 | @day = item[:value] 38 | end 39 | 40 | if item[:type] == :time 41 | @time = item[:value] 42 | end 43 | 44 | if @year && @month && @day && @time 45 | @array_of_full_data << [[@year,@month,@day].join("-"), @time].join(" ") 46 | end 47 | end 48 | end 49 | 50 | @array_of_full_data 51 | end 52 | 53 | def get_year_month_day 54 | set_year_month_day_time 55 | 56 | if @structure 57 | @structure.each do |item| 58 | if item[:type] == :year 59 | @year = item[:value] 60 | end 61 | 62 | if item[:type] == :month 63 | @month = item[:value] 64 | end 65 | 66 | if item[:type] == :day 67 | @day = item[:value] 68 | end 69 | 70 | if @year && @month && @day 71 | @array_of_full_data << [@year,@month,@day].join("-") 72 | end 73 | end 74 | end 75 | 76 | @array_of_full_data 77 | end 78 | 79 | def set_year_month_day_time 80 | @year = nil 81 | @month = nil 82 | @day = nil 83 | @time = nil 84 | end 85 | 86 | end 87 | -------------------------------------------------------------------------------- /lib/dates_from_string/patterns.rb: -------------------------------------------------------------------------------- 1 | module Patterns 2 | PATTERNS = { 3 | [ 4 | /\d{4}-\d{2}-\d{2}/, 5 | /\d{4}-\d{1}-\d{2}/, 6 | /\d{4}-\d{1}-\d{1}/, 7 | /\d{4}-\d{2}-\d{1}/ 8 | ] => ->(string) { string.to_s.split('-') }, 9 | [ 10 | /\d{2}-\d{2}-\d{4}/, 11 | /\d{2}-\d{1}-\d{4}/, 12 | /\d{1}-\d{1}-\d{4}/, 13 | /\d{1}-\d{2}-\d{4}/ 14 | ] => ->(string) { string.to_s.split('-').reverse }, 15 | [ 16 | /\d{4}\.\d{2}\.\d{2}/, 17 | /\d{4}\.\d{2}\.\d{1}/ 18 | ] => ->(string) { string.to_s.split('.') }, 19 | [ 20 | /\d{2}\.\d{2}\.\d{4}/, 21 | /\d{1}\.\d{2}\.\d{4}/ 22 | ] => ->(string) { string.to_s.split('.').reverse }, 23 | [ 24 | /\d{4}\/\d{2}\/\d{2}/, 25 | /\d{4}\/\d{2}\/\d{1}/ 26 | ] => ->(string) { string.to_s.split('/') }, 27 | [ 28 | /\d{2}\/\d{2}\/\d{4}/, 29 | /\d{1}\/\d{2}\/\d{4}/ 30 | ] => ->(string) { string.to_s.split('/').reverse } 31 | }.freeze 32 | 33 | DATE_COUNTRY_FORMAT = { 34 | default: -> { [:year, :month, :day] }, 35 | bra: -> { [:day, :month, :year] }, 36 | usa: -> { [:year, :day, :month] } 37 | }.freeze 38 | end 39 | -------------------------------------------------------------------------------- /lib/dates_from_string/version.rb: -------------------------------------------------------------------------------- 1 | class DatesFromString 2 | VERSION = "1.3.0" 3 | end 4 | -------------------------------------------------------------------------------- /spec/dates_from_string_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe DatesFromString do 4 | subject { DatesFromString.new(['between','-']) } 5 | 6 | describe '#get_structure' do 7 | 8 | it 'find one year' do 9 | input = 'he was born in 1990' 10 | output = [{:type=>:year, :value=>"1990", :distance=>0, :key_words=>[]}] 11 | expect(subject.get_structure(input)).to eq(output) 12 | end 13 | 14 | it 'find two year' do 15 | input = '1990 1988 year of his probably birthday' 16 | output = [ 17 | {:type=>:year, :value=>"1990", :distance=>1, :key_words=>[]}, 18 | {:type=>:year, :value=>"1988", :distance=>0, :key_words=>[]} 19 | ] 20 | 21 | expect(subject.get_structure(input)).to eq(output) 22 | end 23 | 24 | it 'find many year and many distance' do 25 | input = '1990 1988 year 2013 bla bla bla 2015 a b c d i f g qwe 2016' 26 | output = [ 27 | {:type=>:year, :value=>"1990", :distance=>1, :key_words=>[]}, 28 | {:type=>:year, :value=>"1988", :distance=>2, :key_words=>[]}, 29 | {:type=>:year, :value=>"2013", :distance=>4, :key_words=>[]}, 30 | {:type=>:year, :value=>"2015", :distance=>9, :key_words=>[]}, 31 | {:type=>:year, :value=>"2016", :distance=>0, :key_words=>[]} 32 | ] 33 | 34 | expect(subject.get_structure(input)).to eq(output) 35 | end 36 | 37 | it 'find full date year month and day format one' do 38 | input = '2015-02-02' 39 | output = [ 40 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 41 | {:type=>:month, :value=>"02", :distance=>0, :key_words=>[]}, 42 | {:type=>:day, :value=>"02", :distance=>0, :key_words=>[]} 43 | ] 44 | 45 | expect(subject.get_structure(input)).to eq(output) 46 | end 47 | 48 | it 'find full date year month and day format USA' do 49 | date_from_string = DatesFromString.new(date_format: :usa) 50 | input = '01/23/1988' 51 | output = [ 52 | {:type=>:year, :value=>"1988", :distance=>0, :key_words=>[]}, 53 | {:type=>:day, :value=>"23", :distance=>0, :key_words=>[]}, 54 | {:type=>:month, :value=>"01", :distance=>0, :key_words=>[]} 55 | ] 56 | 57 | expect(date_from_string.get_structure(input)).to eq(output) 58 | end 59 | 60 | it 'find full date year month and day format two' do 61 | input = '2015.02.02' 62 | output = [ 63 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 64 | {:type=>:month, :value=>"02", :distance=>0, :key_words=>[]}, 65 | {:type=>:day, :value=>"02", :distance=>0, :key_words=>[]} 66 | ] 67 | 68 | expect(subject.get_structure(input)).to eq(output) 69 | end 70 | 71 | it 'find full date year month and day format three' do 72 | input = '02-02-2015' 73 | output = [ 74 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 75 | {:type=>:month, :value=>"02", :distance=>0, :key_words=>[]}, 76 | {:type=>:day, :value=>"02", :distance=>0, :key_words=>[]} 77 | ] 78 | 79 | expect(subject.get_structure(input)).to eq(output) 80 | end 81 | 82 | it 'find full date year month and day format four' do 83 | input = '02.02.2015' 84 | output = [ 85 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 86 | {:type=>:month, :value=>"02", :distance=>0, :key_words=>[]}, 87 | {:type=>:day, :value=>"02", :distance=>0, :key_words=>[]} 88 | ] 89 | 90 | expect(subject.get_structure(input)).to eq(output) 91 | end 92 | 93 | it 'find full date year month and day format five' do 94 | input = '12/07/2014' 95 | output = [ 96 | {:type=>:year, :value=>"2014", :distance=>0, :key_words=>[]}, 97 | {:type=>:month, :value=>"07", :distance=>0, :key_words=>[]}, 98 | {:type=>:day, :value=>"12", :distance=>0, :key_words=>[]} 99 | ] 100 | 101 | expect(subject.get_structure(input)).to eq(output) 102 | end 103 | 104 | it 'find full date year month and day format six' do 105 | input = '2013/07/09' 106 | output = [ 107 | {:type=>:year, :value=>"2013", :distance=>0, :key_words=>[]}, 108 | {:type=>:month, :value=>"07", :distance=>0, :key_words=>[]}, 109 | {:type=>:day, :value=>"09", :distance=>0, :key_words=>[]} 110 | ] 111 | 112 | expect(subject.get_structure(input)).to eq(output) 113 | end 114 | 115 | it 'find full date and year ' do 116 | input = '2013/07/09 one date and he born in 1990' 117 | output = [ 118 | {:type=>:year, :value=>"2013", :distance=>0, :key_words=>[]}, 119 | {:type=>:month, :value=>"07", :distance=>0, :key_words=>[]}, 120 | {:type=>:day, :value=>"09", :distance=>7, :key_words=>[]}, 121 | {:type=>:year, :value=>"1990", :distance=>0, :key_words=>[]} 122 | ] 123 | 124 | expect(subject.get_structure(input)).to eq(output) 125 | end 126 | 127 | it 'find short date one' do 128 | input = '00/00/2015 one year' 129 | output = [ 130 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 131 | {:type=>:month, :value=>"00", :distance=>0, :key_words=>[]}, 132 | {:type=>:day, :value=>"00", :distance=>0, :key_words=>[]}, 133 | ] 134 | 135 | expect(subject.get_structure(input)).to eq(output) 136 | end 137 | 138 | it 'find short date two' do 139 | input = '00/10/2015 one year' 140 | output = [ 141 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 142 | {:type=>:month, :value=>"10", :distance=>0, :key_words=>[]}, 143 | {:type=>:day, :value=>"00", :distance=>0, :key_words=>[]}, 144 | ] 145 | 146 | expect(subject.get_structure(input)).to eq(output) 147 | end 148 | 149 | it 'find short date three' do 150 | input = '2015/10/00 one year' 151 | output = [ 152 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 153 | {:type=>:month, :value=>"10", :distance=>0, :key_words=>[]}, 154 | {:type=>:day, :value=>"00", :distance=>0, :key_words=>[]}, 155 | ] 156 | 157 | expect(subject.get_structure(input)).to eq(output) 158 | end 159 | 160 | it 'find short date four' do 161 | input = '2015/00/00 one year' 162 | output = [ 163 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 164 | {:type=>:month, :value=>"00", :distance=>0, :key_words=>[]}, 165 | {:type=>:day, :value=>"00", :distance=>0, :key_words=>[]}, 166 | ] 167 | 168 | expect(subject.get_structure(input)).to eq(output) 169 | end 170 | 171 | it 'year and special word between' do 172 | input = '1988 between 1990' 173 | output = [ 174 | {:type=>:year, :value=>"1988", :distance=>2, :key_words=>['between']}, 175 | {:type=>:year, :value=>"1990", :distance=>0, :key_words=>[]}, 176 | ] 177 | 178 | expect(subject.get_structure(input)).to eq(output) 179 | end 180 | 181 | it 'year and special sympol' do 182 | input = '1988 - 1990' 183 | output = [ 184 | {:type=>:year, :value=>"1988", :distance=>2, :key_words=>['-']}, 185 | {:type=>:year, :value=>"1990", :distance=>0, :key_words=>[]}, 186 | ] 187 | 188 | expect(subject.get_structure(input)).to eq(output) 189 | end 190 | 191 | it 'year and special sympol other way' do 192 | input = '1988-1990' 193 | output = [ 194 | {:type=>:year, :value=>"1988", :distance=>0, :key_words=>['-']}, 195 | {:type=>:year, :value=>"1990", :distance=>0, :key_words=>[]}, 196 | ] 197 | 198 | expect(subject.get_structure(input)).to eq(output) 199 | end 200 | 201 | it 'year and special sympol other way and one more year' do 202 | input = '1988-1990 and 2000' 203 | output = [ 204 | {:type=>:year, :value=>"1988", :distance=>0, :key_words=>['-']}, 205 | {:type=>:year, :value=>"1990", :distance=>2, :key_words=>[]}, 206 | {:type=>:year, :value=>"2000", :distance=>0, :key_words=>[]}, 207 | ] 208 | 209 | expect(subject.get_structure(input)).to eq(output) 210 | end 211 | 212 | it 'year and special sympol other way and year and full date' do 213 | input = '1988-1990 and 2000 and one more date 28.04.2015' 214 | output = [ 215 | {:type=>:year, :value=>"1988", :distance=>0, :key_words=>['-']}, 216 | {:type=>:year, :value=>"1990", :distance=>2, :key_words=>[]}, 217 | {:type=>:year, :value=>"2000", :distance=>5, :key_words=>[]}, 218 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 219 | {:type=>:month, :value=>"04", :distance=>0, :key_words=>[]}, 220 | {:type=>:day, :value=>"28", :distance=>0, :key_words=>[]}, 221 | ] 222 | 223 | expect(subject.get_structure(input)).to eq(output) 224 | end 225 | 226 | it 'month by string and year' do 227 | input = 'August 1961' 228 | output = [ 229 | {:type=>:month, :value=>"08", :distance=>1, :key_words=>[]}, 230 | {:type=>:year, :value=>"1961", :distance=>0, :key_words=>[]}, 231 | ] 232 | 233 | expect(subject.get_structure(input)).to eq(output) 234 | end 235 | 236 | it 'month by string and year and one more' do 237 | input = 'August 1961' 238 | output = [ 239 | {:type=>:month, :value=>"08", :distance=>1, :key_words=>[]}, 240 | {:type=>:year, :value=>"1961", :distance=>0, :key_words=>[]}, 241 | ] 242 | 243 | expect(subject.get_structure(input)).to eq(output) 244 | 245 | input_2 = '2012' 246 | output_2 = [ 247 | {:type=>:year, :value=>"2012", :distance=>0, :key_words=>[]}, 248 | ] 249 | 250 | expect(subject.get_structure(input_2)).to eq(output_2) 251 | end 252 | 253 | it 'two year and between' do 254 | input = 'Between 1984 and 1986' 255 | output = [ 256 | {:type=>:year, :value=>"1984", :distance=>2, :key_words=>[]}, 257 | {:type=>:year, :value=>"1986", :distance=>0, :key_words=>[]}, 258 | ] 259 | 260 | expect(subject.get_structure(input)).to eq(output) 261 | end 262 | 263 | it 'day month by string and year' do 264 | input = '10 Dec 1948' 265 | output = [ 266 | {:type=>:day, :value=>"10", :distance=>1, :key_words=>[]}, 267 | {:type=>:month, :value=>"12", :distance=>1, :key_words=>[]}, 268 | {:type=>:year, :value=>"1948", :distance=>0, :key_words=>[]} 269 | ] 270 | 271 | expect(subject.get_structure(input)).to eq(output) 272 | end 273 | 274 | it 'day month ny string and year' do 275 | input = '10 Dec 1948 ane one more year 1988' 276 | output = [ 277 | {:type=>:day, :value=>"10", :distance=>1, :key_words=>[]}, 278 | {:type=>:month, :value=>"12", :distance=>1, :key_words=>[]}, 279 | {:type=>:year, :value=>"1948", :distance=>5, :key_words=>[]}, 280 | {:type=>:year, :value=>"1988", :distance=>0, :key_words=>[]} 281 | ] 282 | 283 | expect(subject.get_structure(input)).to eq(output) 284 | end 285 | 286 | it 'day month by string full month' do 287 | input = '10 April 1948' 288 | output = [ 289 | {:type=>:day, :value=>"10", :distance=>1, :key_words=>[]}, 290 | {:type=>:month, :value=>"04", :distance=>1, :key_words=>[]}, 291 | {:type=>:year, :value=>"1948", :distance=>0, :key_words=>[]}, 292 | ] 293 | 294 | expect(subject.get_structure(input)).to eq(output) 295 | end 296 | 297 | it 'grap date from not valid string one' do 298 | input = '[CDATA[11.07.1989]]' 299 | output = [ 300 | {:type=>:year, :value=>"1989", :distance=>0, :key_words=>[]}, 301 | {:type=>:month, :value=>"07", :distance=>0, :key_words=>[]}, 302 | {:type=>:day, :value=>"11", :distance=>0, :key_words=>[]}, 303 | ] 304 | 305 | expect(subject.get_structure(input)).to eq(output) 306 | end 307 | 308 | it 'grap date circa year and full data' do 309 | input = 'circa 1960 and full date 07 Jun 1941' 310 | output = [ 311 | {:type=>:year, :value=>"1960", :distance=>4, :key_words=>[]}, 312 | {:type=>:day, :value=>"07", :distance=>1, :key_words=>[]}, 313 | {:type=>:month, :value=>"06", :distance=>1, :key_words=>[]}, 314 | {:type=>:year, :value=>"1941", :distance=>0, :key_words=>[]}, 315 | ] 316 | 317 | expect(subject.get_structure(input)).to eq(output) 318 | end 319 | 320 | it 'grap date between tho dates and add key words' do 321 | obj = DatesFromString.new(['and']) 322 | input = 'between 1960 and 1965' 323 | output = [ 324 | {:type=>:year, :value=>"1960", :distance=>2, :key_words=>['and']}, 325 | {:type=>:year, :value=>"1965", :distance=>0, :key_words=>[]}, 326 | ] 327 | 328 | expect(obj.get_structure(input)).to eq(output) 329 | end 330 | 331 | it 'grap data from long text' do 332 | input = "For 16 years Putin was an officer in the KGB, 333 | rising to the rank of Lieutenant Colonel before 334 | he retired to enter politics in his native Saint 335 | Petersburg in 1991. He moved to Moscow in 1996 and 336 | joined President Boris Yeltsin's administration where 337 | he rose quickly, becoming Acting President on 31 December 338 | 1999 when Yeltsin unexpectedly resigned" 339 | output = [ 340 | {:type=>:day, :value=>"16", :distance=>28, :key_words=>[]}, 341 | {:type=>:year, :value=>"1991", :distance=>6, :key_words=>[]}, 342 | {:type=>:year, :value=>"1996", :distance=>15, :key_words=>[]}, 343 | {:type=>:day, :value=>"31", :distance=>1, :key_words=>[]}, 344 | {:type=>:month, :value=>"12", :distance=>1, :key_words=>[]}, 345 | {:type=>:year, :value=>"1999", :distance=>0, :key_words=>[]}, 346 | ] 347 | expect(subject.get_structure(input)).to eq(output) 348 | end 349 | 350 | it 'grap data from long text two' do 351 | input = "In September 2011, following a change in the law extending 352 | the presidential term from four years to six,[5] Putin announced 353 | that he would seek a third, non-consecutive term as President in 354 | the 2012 presidential election, an announcement which led to 355 | large-scale protests in many Russian cities. In March 2012 he won the election, 356 | which was criticized for procedural irregularities, and is serving a six-year term" 357 | output = [ 358 | {:type=>:month, :value=>"09", :distance=>1, :key_words=>[]}, 359 | {:type=>:year, :value=>"2011", :distance=>30, :key_words=>[]}, 360 | {:type=>:year, :value=>"2012", :distance=>15, :key_words=>[]}, 361 | {:type=>:month, :value=>"03", :distance=>1, :key_words=>[]}, 362 | {:type=>:year, :value=>"2012", :distance=>0, :key_words=>[]}, 363 | ] 364 | expect(subject.get_structure(input)).to eq(output) 365 | end 366 | 367 | it 'grap data from long text three' do 368 | input = "During Putin first premiership and presidency (1999–2008) 369 | real incomes in Russia rose by a factor of 2.5, while real 370 | wages more than tripled; unemployment and poverty more than halved. 371 | Russians' self-assessed life satisfaction also rose significantly. 372 | Putin's first presidency was marked by high economic growth: the 373 | Russian economy grew for eight straight years, seeing GDP increase by 374 | 72% in PPP (as for nominal GDP, 600%).This growth was a combined result 375 | of the 2000s commodities boom, high oil prices, as well as prudent economic 376 | and fiscal policies." 377 | output = [ 378 | {:type=>:year, :value=>"1999", :distance=>6, :key_words=>['-']}, 379 | {:type=>:year, :value=>"2008", :distance=>0, :key_words=>[]}, 380 | ] 381 | expect(subject.get_structure(input)).to eq(output) 382 | end 383 | 384 | it 'find month.year' do 385 | input = "10.1964" 386 | output = [ 387 | {:type=>:year, :value=>"1964", :distance=>0, :key_words=>[]}, 388 | {:type=>:month, :value=>"10", :distance=>0, :key_words=>[]}, 389 | ] 390 | expect(subject.get_structure(input)).to eq(output) 391 | end 392 | 393 | it 'find year.month' do 394 | input = "1964.10" 395 | output = [ 396 | {:type=>:year, :value=>"1964", :distance=>0, :key_words=>[]}, 397 | {:type=>:month, :value=>"10", :distance=>0, :key_words=>[]}, 398 | ] 399 | expect(subject.get_structure(input)).to eq(output) 400 | end 401 | 402 | it 'no string' do 403 | input = "" 404 | output = nil 405 | expect(subject.get_structure(input)).to eq(output) 406 | end 407 | 408 | it 'nil' do 409 | input = nil 410 | output = nil 411 | expect(subject.get_structure(input)).to eq(output) 412 | end 413 | 414 | it 'no date' do 415 | input = "bla bla no date" 416 | output = [] 417 | expect(subject.get_structure(input)).to eq(output) 418 | end 419 | 420 | it 'no date' do 421 | input = "bla bla no date" 422 | output = [] 423 | expect(subject.get_structure(input)).to eq(output) 424 | end 425 | 426 | it 'get crash date' do 427 | input = "29-2-1969" 428 | output = [ 429 | {:type=>:year, :value=>"1969", :distance=>0, :key_words=>[]}, 430 | {:type=>:month, :value=>"2", :distance=>0, :key_words=>[]}, 431 | {:type=>:day, :value=>"29", :distance=>0, :key_words=>[]}, 432 | ] 433 | expect(subject.get_structure(input)).to eq(output) 434 | end 435 | 436 | it 'get crash date two' do 437 | input = "1969-2-29" 438 | output = [ 439 | {:type=>:year, :value=>"1969", :distance=>0, :key_words=>[]}, 440 | {:type=>:month, :value=>"2", :distance=>0, :key_words=>[]}, 441 | {:type=>:day, :value=>"29", :distance=>0, :key_words=>[]}, 442 | ] 443 | expect(subject.get_structure(input)).to eq(output) 444 | end 445 | 446 | it 'get crash date two' do 447 | input = "1969-2-2" 448 | output = [ 449 | {:type=>:year, :value=>"1969", :distance=>0, :key_words=>[]}, 450 | {:type=>:month, :value=>"2", :distance=>0, :key_words=>[]}, 451 | {:type=>:day, :value=>"2", :distance=>0, :key_words=>[]}, 452 | ] 453 | expect(subject.get_structure(input)).to eq(output) 454 | end 455 | 456 | it 'get crash date one more' do 457 | input = "2-2-1969" 458 | output = [ 459 | {:type=>:year, :value=>"1969", :distance=>0, :key_words=>[]}, 460 | {:type=>:month, :value=>"2", :distance=>0, :key_words=>[]}, 461 | {:type=>:day, :value=>"2", :distance=>0, :key_words=>[]}, 462 | ] 463 | expect(subject.get_structure(input)).to eq(output) 464 | end 465 | 466 | it 'get crash date one more' do 467 | input = "2-02-1969" 468 | output = [ 469 | {:type=>:year, :value=>"1969", :distance=>0, :key_words=>[]}, 470 | {:type=>:month, :value=>"02", :distance=>0, :key_words=>[]}, 471 | {:type=>:day, :value=>"2", :distance=>0, :key_words=>[]}, 472 | ] 473 | expect(subject.get_structure(input)).to eq(output) 474 | end 475 | 476 | it 'get crash date revert' do 477 | input = "1969-02-2" 478 | output = [ 479 | {:type=>:year, :value=>"1969", :distance=>0, :key_words=>[]}, 480 | {:type=>:month, :value=>"02", :distance=>0, :key_words=>[]}, 481 | {:type=>:day, :value=>"2", :distance=>0, :key_words=>[]}, 482 | ] 483 | expect(subject.get_structure(input)).to eq(output) 484 | end 485 | 486 | 487 | it 'find full date year month and day and time format one' do 488 | input = '2015-02-02 in 23:00:10' 489 | output = [ 490 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 491 | {:type=>:month, :value=>"02", :distance=>0, :key_words=>[]}, 492 | {:type=>:day, :value=>"02", :distance=>2, :key_words=>[]}, 493 | {:type=>:time, :value=>"23:00:10", :distance=>0, :key_words=>[]} 494 | ] 495 | 496 | expect(subject.get_structure(input)).to eq(output) 497 | end 498 | 499 | it 'finds full date year month and day in USA comma-delimited format' do 500 | input = 'February 2, 2015' 501 | output = [ 502 | {:type=>:month, :value=>"02", :distance=>1, :key_words=>[]}, 503 | {:type=>:day, :value=>"2", :distance=>1, :key_words=>[]}, 504 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]} 505 | ] 506 | 507 | expect(subject.get_structure(input)).to eq(output) 508 | end 509 | 510 | it 'finds day when sepcified with a single digit' do 511 | input = '2 Feb in the year 2015' 512 | output = [ 513 | {:type=>:day, :value=>"2", :distance=>1, :key_words=>[]}, 514 | {:type=>:month, :value=>"02", :distance=>4, :key_words=>[]}, 515 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]} 516 | ] 517 | 518 | expect(subject.get_structure(input)).to eq(output) 519 | end 520 | 521 | it 'finds date when abbreviated month buttressed by comma' do 522 | input = '2 Feb, 2015' 523 | output = [ 524 | {:type=>:day, :value=>"2", :distance=>1, :key_words=>[]}, 525 | {:type=>:month, :value=>"02", :distance=>1, :key_words=>[]}, 526 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]} 527 | ] 528 | 529 | expect(subject.get_structure(input)).to eq(output) 530 | end 531 | 532 | it 'finds date when month buttressed by comma' do 533 | input = '2 February, 2015' 534 | output = [ 535 | {:type=>:day, :value=>"2", :distance=>1, :key_words=>[]}, 536 | {:type=>:month, :value=>"02", :distance=>1, :key_words=>[]}, 537 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]} 538 | ] 539 | 540 | expect(subject.get_structure(input)).to eq(output) 541 | end 542 | 543 | it 'finds day with a specified "nd" ordinal' do 544 | dates_from_string_with_ordinals = DatesFromString.new(['between','-'], ordinals: ['nd']) 545 | input = '2nd of Feb, 2015' 546 | output = [ 547 | {:type=>:day, :value=>"2", :distance=>2, :key_words=>[]}, 548 | {:type=>:month, :value=>"02", :distance=>1, :key_words=>[]}, 549 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]} 550 | ] 551 | 552 | expect(dates_from_string_with_ordinals.get_structure(input)).to eq(output) 553 | end 554 | 555 | it 'finds day with a specified "st" ordinal' do 556 | dates_from_string_with_ordinals = DatesFromString.new(['between','-'], ordinals: ['st']) 557 | input = '1st of Feb, 2015' 558 | output = [ 559 | {:type=>:day, :value=>"1", :distance=>2, :key_words=>[]}, 560 | {:type=>:month, :value=>"02", :distance=>1, :key_words=>[]}, 561 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]} 562 | ] 563 | 564 | expect(dates_from_string_with_ordinals.get_structure(input)).to eq(output) 565 | end 566 | 567 | it 'finds day with a specified "th" ordinal' do 568 | dates_from_string_with_ordinals = DatesFromString.new(['between','-'], ordinals: ['th']) 569 | input = '4th of Feb, 2015' 570 | output = [ 571 | {:type=>:day, :value=>"4", :distance=>2, :key_words=>[]}, 572 | {:type=>:month, :value=>"02", :distance=>1, :key_words=>[]}, 573 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]} 574 | ] 575 | 576 | expect(dates_from_string_with_ordinals.get_structure(input)).to eq(output) 577 | end 578 | 579 | it 'find dates in simple structure' do 580 | input = '23.04.2013' 581 | output = ['2013-04-23'] 582 | 583 | expect(subject.find_date(input)).to eq(output) 584 | end 585 | 586 | it 'find dates in simple structure 2' do 587 | input = '2015-04-01' 588 | output = ['2015-04-01'] 589 | 590 | expect(subject.find_date(input)).to eq(output) 591 | end 592 | 593 | it 'find dates in simple structure 3' do 594 | input = '01-04-2015' 595 | output = ['2015-04-01'] 596 | 597 | expect(subject.find_date(input)).to eq(output) 598 | end 599 | 600 | it 'find dates in simple structure 4' do 601 | input = 'bla bla bla 01-04-2015' 602 | output = ['2015-04-01'] 603 | 604 | expect(subject.find_date(input)).to eq(output) 605 | end 606 | 607 | it 'find dates in simple structure 5' do 608 | input = 'bla bla bla 01-04-2015 идф идф идф' 609 | output = ['2015-04-01'] 610 | 611 | expect(subject.find_date(input)).to eq(output) 612 | end 613 | 614 | it 'find single digit days' do 615 | input = '3/13/2017' 616 | output = ['2017-13-3'] 617 | 618 | expect(subject.find_date(input)).to eq(output) 619 | end 620 | 621 | it 'find dates in simple structure 5' do 622 | input = "" 623 | output = [] 624 | 625 | expect(subject.find_date(input)).to eq(output) 626 | end 627 | 628 | it 'find full date year month and day and time format two' do 629 | input = 'забрать машину из ремонта 2015-02-02 23:00:10' 630 | output = [ 631 | {:type=>:year, :value=>"2015", :distance=>0, :key_words=>[]}, 632 | {:type=>:month, :value=>"02", :distance=>0, :key_words=>[]}, 633 | {:type=>:day, :value=>"02", :distance=>5, :key_words=>[]}, 634 | {:type=>:time, :value=>"23:00:10", :distance=>0, :key_words=>[]} 635 | ] 636 | 637 | expect(subject.get_structure(input)).to eq(output) 638 | end 639 | 640 | it 'find dates in simple structure 6' do 641 | input = "забрать машину из ремонта 2015-02-02 23:00:10" 642 | output = ["2015-02-02 23:00:10"] 643 | 644 | expect(subject.find_date(input)).to eq(output) 645 | end 646 | 647 | it 'find dates in simple structure 7' do 648 | input = "Создай задачу забрать машину из ремонта 2015-02-02 в 23:00:10" 649 | output = ["2015-02-02 23:00:10"] 650 | 651 | expect(subject.find_date(input)).to eq(output) 652 | end 653 | 654 | it 'find dates in simple structure 8' do 655 | input = "Создай задачу забрать машину из ремонта 2015-02-02 в 23:00" 656 | output = ["2015-02-02 23:00"] 657 | 658 | expect(subject.find_date(input)).to eq(output) 659 | end 660 | 661 | it 'find dates in simple structure 9' do 662 | input = "Создай задачу забрать машину из ремонта 2015-02-02 23:00" 663 | output = "Создай задачу забрать машину из ремонта" 664 | subject.find_date(input) 665 | expect(subject.get_clear_text).to eq(output) 666 | end 667 | 668 | it 'find dates in simple structure 10' do 669 | input = "Создай задачу забрать машину из ремонта 2015-02-02 23:30:40" 670 | output = "Создай задачу забрать машину из ремонта" 671 | subject.find_date(input) 672 | expect(subject.get_clear_text).to eq(output) 673 | end 674 | 675 | it "find year in email one" do 676 | date_from_string = DatesFromString.new() 677 | input = 'test1988@gmail.com' 678 | output = "1988" 679 | 680 | expect(date_from_string.email_date(input)).to eq(output) 681 | end 682 | 683 | it "find year in email two" do 684 | date_from_string = DatesFromString.new() 685 | input = '1test1988@gmail.com' 686 | output = "1988" 687 | 688 | expect(date_from_string.email_date(input)).to eq(output) 689 | end 690 | 691 | it "find year in email three" do 692 | date_from_string = DatesFromString.new() 693 | input = '1test11988@gmail.com' 694 | output = "1988" 695 | 696 | expect(date_from_string.email_date(input)).to eq(output) 697 | end 698 | 699 | end 700 | end 701 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) 2 | require 'dates_from_string' 3 | --------------------------------------------------------------------------------