num2words 0.1.6 → 0.2.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 +4 -4
- data/CHANGELOG.md +43 -0
- data/README.md +57 -16
- data/bin/console +2 -14
- data/config/locales/ru.yml +4 -0
- data/exe/num2words-console +7 -0
- data/lib/num2words/console.rb +16 -0
- data/lib/num2words/converter.rb +58 -19
- data/lib/num2words/version.rb +1 -1
- data/num2words.gemspec +1 -1
- metadata +9 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fbd7bda19d94f161e928ec326ce532c9c301746daaa371a041b859aa7262d4d9
|
|
4
|
+
data.tar.gz: ec621319e9ce5de5657c01d87c9b91cb88da31516cd06c07629924558e5c6017
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '092432a7d992343146c93337af17af5ea595ab06fff83793f81813ba55c7c4282b66e8bcc0598e82eba7db43e63131b1fba0f63332ede4984b10ef606e77698b'
|
|
7
|
+
data.tar.gz: dfefff68054582dd62771c9fa87b2ff21996a73ae0d4b0b219b67178a06a8c393ac20ef5f8029bf5f32c77c2ef36bb66760d743c528e066f361ba8592f431013
|
data/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,49 @@
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## [0.2.0] - 2026-05-31
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- Поддержка строковых дробей с точкой и запятой:
|
|
18
|
+
```ruby
|
|
19
|
+
Num2words.to_words("3.5", :ru)
|
|
20
|
+
Num2words.to_words("3,5", :ru)
|
|
21
|
+
```
|
|
22
|
+
- Опция `joiner: :and` для разговорного соединителя в дробях:
|
|
23
|
+
```ruby
|
|
24
|
+
Num2words.to_words(0.5, :ru, joiner: :and)
|
|
25
|
+
# => "ноль и пять десятых"
|
|
26
|
+
```
|
|
27
|
+
- Опция `date_case: :genitive` для дат в контексте "когда?":
|
|
28
|
+
```ruby
|
|
29
|
+
Num2words.to_words("2024-08-21", :ru, date_case: :genitive)
|
|
30
|
+
# => "двадцать первого августа две тысячи двадцать четвёртого года"
|
|
31
|
+
```
|
|
32
|
+
- Опция `minor:` для управления выводом младшей денежной единицы:
|
|
33
|
+
- `:always` — всегда выводить копейки/центы;
|
|
34
|
+
- `:nonzero` — выводить только ненулевую младшую единицу;
|
|
35
|
+
- `:never` — не выводить младшую единицу.
|
|
36
|
+
- Поддержка строковых сумм и `BigDecimal` в `to_currency`:
|
|
37
|
+
```ruby
|
|
38
|
+
Num2words.to_currency("21,05", :ru)
|
|
39
|
+
Num2words.to_currency(BigDecimal("21.05"), :ru)
|
|
40
|
+
```
|
|
41
|
+
- Команда `num2words-console` для быстрого запуска интерактивной консоли после установки гема.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
- Русские даты по умолчанию выводят день в именительном падеже:
|
|
45
|
+
```ruby
|
|
46
|
+
Num2words.to_words("2024-08-21", :ru)
|
|
47
|
+
# => "двадцать первое августа две тысячи двадцать четвёртого года"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
- `DateTime` теперь корректно определяется как дата и время, а не только как дата.
|
|
52
|
+
- Добавлена валидация опций `joiner`, `date_case` и `minor`.
|
|
53
|
+
|
|
54
|
+
### Planned
|
|
12
55
|
- Добавление новых локалей (планируется расширение поддерживаемых языков).
|
|
13
56
|
- Оптимизация производительности при больших числах.
|
|
14
57
|
- Улучшения документации.
|
data/README.md
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
## ✨ Основные возможности
|
|
8
8
|
|
|
9
9
|
- Поддержка **чисел, времени, дат и валют**:
|
|
10
|
-
- `Integer`
|
|
11
|
-
- `Float`
|
|
12
|
-
- `Time / DateTime`
|
|
13
|
-
- `Float.to_currency`
|
|
10
|
+
- `Integer` -> `123.to_words(:ru)` -> `"сто двадцать три"`
|
|
11
|
+
- `Float` -> `12.5.to_words(:en)` -> `"twelve and five tenths"`
|
|
12
|
+
- `Time / DateTime` -> `"2024-08-21 14:35:42".to_words(:ru, :time)` -> `"четырнадцать часов тридцать пять минут сорок две секунды"`
|
|
13
|
+
- `Float.to_currency` -> `12.5.to_currency(:ru)` -> `"двенадцать рублей пятьдесят копеек"`
|
|
14
14
|
- Кастомизация вывода:
|
|
15
|
-
- Краткая форма (`short: true`)
|
|
15
|
+
- Краткая форма (`short: true`) -> `"четырнадцать часов тридцать пять минут"`
|
|
16
16
|
- Форматы времени (`:hours_only`, `:hours_minutes`, `:hours_minutes_seconds`)
|
|
17
17
|
- Выбор локали: `:ru`, `:en` (из коробки), легко расширить YAML-файлами
|
|
18
18
|
- Расширение **Integer**, **Float**, **Date**, **Time**, **DateTime** удобными методами.
|
|
@@ -48,24 +48,54 @@ require "num2words"
|
|
|
48
48
|
### 🔢 Числа
|
|
49
49
|
```ruby
|
|
50
50
|
# Integer
|
|
51
|
-
123.to_words(:ru)
|
|
52
|
-
|
|
51
|
+
123.to_words(:ru)
|
|
52
|
+
# => "сто двадцать три"
|
|
53
|
+
|
|
54
|
+
123.to_words(:en)
|
|
55
|
+
# => "one hundred twenty three"
|
|
53
56
|
|
|
54
57
|
# Float
|
|
55
|
-
45.67.to_words(:ru)
|
|
56
|
-
|
|
58
|
+
45.67.to_words(:ru)
|
|
59
|
+
# => "сорок пять целых шестьдесят семь сотых"
|
|
60
|
+
|
|
61
|
+
"45,67".to_words(:ru)
|
|
62
|
+
# => "сорок пять целых шестьдесят семь сотых"
|
|
63
|
+
|
|
64
|
+
45.67.to_words(:ru, joiner: :and)
|
|
65
|
+
# => "сорок пять и шестьдесят семь сотых"
|
|
66
|
+
|
|
67
|
+
45.67.to_words(:en)
|
|
68
|
+
# => "forty five and sixty seven hundredths"
|
|
57
69
|
```
|
|
58
70
|
|
|
59
71
|
### 💰 Валюта
|
|
60
72
|
```ruby
|
|
61
|
-
21.05.to_currency(:ru)
|
|
62
|
-
|
|
73
|
+
21.05.to_currency(:ru)
|
|
74
|
+
# => "двадцать один рубль пять копеек"
|
|
75
|
+
|
|
76
|
+
"21,05".to_currency(:ru)
|
|
77
|
+
# => "двадцать один рубль пять копеек"
|
|
78
|
+
|
|
79
|
+
Num2words.to_currency(BigDecimal("21.05"), :ru)
|
|
80
|
+
# => "двадцать один рубль пять копеек"
|
|
81
|
+
|
|
82
|
+
1.to_currency(:ru, minor: :nonzero)
|
|
83
|
+
# => "один рубль"
|
|
84
|
+
|
|
85
|
+
1.25.to_currency(:ru, minor: :never)
|
|
86
|
+
# => "один рубль"
|
|
87
|
+
|
|
88
|
+
12.5.to_currency(:en)
|
|
89
|
+
# => "twelve dollars fifty cents"
|
|
63
90
|
```
|
|
64
91
|
|
|
65
92
|
### 📅 Дата
|
|
66
93
|
```ruby
|
|
67
94
|
"2024-08-21".to_words(:ru, :date)
|
|
68
|
-
# => "двадцать первое августа две тысячи двадцать
|
|
95
|
+
# => "двадцать первое августа две тысячи двадцать четвёртого года"
|
|
96
|
+
|
|
97
|
+
"2024-08-21".to_words(:ru, :date, date_case: :genitive)
|
|
98
|
+
# => "двадцать первого августа две тысячи двадцать четвёртого года"
|
|
69
99
|
|
|
70
100
|
"2024-08-21".to_words(:en, :date)
|
|
71
101
|
# => "the twenty-first of August, two thousand twenty four"
|
|
@@ -87,6 +117,9 @@ require "num2words"
|
|
|
87
117
|
|
|
88
118
|
```ruby
|
|
89
119
|
"2024-08-21 14:35:42".to_words(:ru)
|
|
120
|
+
# => "двадцать первое августа две тысячи двадцать четвёртого года, четырнадцать часов тридцать пять минут сорок две секунды"
|
|
121
|
+
|
|
122
|
+
"2024-08-21 14:35:42".to_words(:ru, date_case: :genitive)
|
|
90
123
|
# => "двадцать первого августа две тысячи двадцать четвёртого года, четырнадцать часов тридцать пять минут сорок две секунды"
|
|
91
124
|
|
|
92
125
|
"2024-08-21 14:35:42".to_words(:en)
|
|
@@ -98,6 +131,8 @@ require "num2words"
|
|
|
98
131
|
- `locale: :ru | :en` — язык (по умолчанию берётся I18n.locale или :ru).
|
|
99
132
|
- `:date, :time, :datetime` — формат преобразования для строк.
|
|
100
133
|
- `short: true` — краткая форма для даты/времени.
|
|
134
|
+
- `joiner: :and` — разговорный соединитель для дробей: `"ноль и пять десятых"` вместо `"ноль целых пять десятых"`.
|
|
135
|
+
- `date_case: :genitive` — родительный падеж дня для дат в контексте “когда?”.
|
|
101
136
|
- `Num2words.to_words(number, locale: :en)` — универсальный способ вызова без расширения базовых классов.
|
|
102
137
|
- `Num2words.to_currency(number)` — преобразование число в валюту.
|
|
103
138
|
|
|
@@ -106,18 +141,24 @@ require "num2words"
|
|
|
106
141
|
Num2words поддерживает интерактивную консоль для быстрого тестирования.
|
|
107
142
|
Это удобно при работе с разными числами и языками.
|
|
108
143
|
|
|
109
|
-
#### Запуск консоли
|
|
144
|
+
#### Запуск консоли из репозитория
|
|
110
145
|
|
|
111
146
|
```bash
|
|
112
147
|
bin/console
|
|
113
148
|
```
|
|
114
149
|
|
|
150
|
+
#### Запуск консоли после установки гема
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
num2words-console
|
|
154
|
+
```
|
|
155
|
+
|
|
115
156
|
После запуска появится приветственное сообщение:
|
|
116
157
|
|
|
117
158
|
```bash
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
159
|
+
Добро пожаловать в консоль num2words!
|
|
160
|
+
Можете использовать: Num2words.to_words(2025)
|
|
161
|
+
-------------------------------------------------------------
|
|
121
162
|
```
|
|
122
163
|
|
|
123
164
|
👉 Это позволяет проверять работу гема без написания отдельных скриптов.
|
data/bin/console
CHANGED
|
@@ -3,18 +3,6 @@
|
|
|
3
3
|
|
|
4
4
|
require "bundler/setup"
|
|
5
5
|
require "num2words"
|
|
6
|
+
require "num2words/console"
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
# with your gem easier. You can also use a different console, if you like.
|
|
9
|
-
|
|
10
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
11
|
-
# require "pry"
|
|
12
|
-
# Pry.start
|
|
13
|
-
|
|
14
|
-
# Красивое приветствие
|
|
15
|
-
puts "👋 Добро пожаловать в консоль num2words!"
|
|
16
|
-
puts "Можете использовать: Num2words.to_words(#{Time.now.year})"
|
|
17
|
-
puts "-------------------------------------------------------------"
|
|
18
|
-
|
|
19
|
-
require "irb"
|
|
20
|
-
IRB.start(__FILE__)
|
|
8
|
+
Num2words::Console.start
|
data/config/locales/ru.yml
CHANGED
|
@@ -48,6 +48,10 @@ ru:
|
|
|
48
48
|
"десятого", "одиннадцатого", "двенадцатого", "тринадцатого", "четырнадцатого", "пятнадцатого", "шестнадцатого", "семнадцатого", "восемнадцатого", "девятнадцатого",
|
|
49
49
|
"двадцатого", "двадцать первого", "двадцать второго", "двадцать третьего", "двадцать четвёртого", "двадцать пятого", "двадцать шестого", "двадцать седьмого", "двадцать восьмого", "двадцать девятого",
|
|
50
50
|
"тридцатого", "тридцать первого"]
|
|
51
|
+
neuter: ["первое", "второе", "третье", "четвёртое", "пятое", "шестое", "седьмое", "восьмое", "девятое",
|
|
52
|
+
"десятое", "одиннадцатое", "двенадцатое", "тринадцатое", "четырнадцатое", "пятнадцатое", "шестнадцатое", "семнадцатое", "восемнадцатое", "девятнадцатое",
|
|
53
|
+
"двадцатое", "двадцать первое", "двадцать второе", "двадцать третье", "двадцать четвёртое", "двадцать пятое", "двадцать шестое", "двадцать седьмое", "двадцать восьмое", "двадцать девятое",
|
|
54
|
+
"тридцатое", "тридцать первое"]
|
|
51
55
|
|
|
52
56
|
datetime:
|
|
53
57
|
template: "%{date}, %{time}"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Num2words
|
|
4
|
+
module Console
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def start
|
|
8
|
+
puts "Добро пожаловать в консоль num2words!"
|
|
9
|
+
puts "Можете использовать: Num2words.to_words(#{Time.now.year})"
|
|
10
|
+
puts "-------------------------------------------------------------"
|
|
11
|
+
|
|
12
|
+
require "irb"
|
|
13
|
+
IRB.start(__FILE__)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/num2words/converter.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "date"
|
|
4
4
|
require "time"
|
|
5
|
+
require "bigdecimal"
|
|
5
6
|
|
|
6
7
|
module Num2words
|
|
7
8
|
class Converter
|
|
@@ -15,14 +16,19 @@ module Num2words
|
|
|
15
16
|
style = opts[:style] || :fraction
|
|
16
17
|
word_case = opts[:word_case] || :default
|
|
17
18
|
date_format = opts[:format] || :default
|
|
19
|
+
date_case = opts[:date_case] || :default
|
|
20
|
+
joiner = opts[:joiner] || :default
|
|
21
|
+
|
|
22
|
+
validate_option!(:date_case, date_case, %i[default genitive])
|
|
23
|
+
validate_option!(:joiner, joiner, %i[default and])
|
|
18
24
|
|
|
19
25
|
locale_data = Locales[locale]
|
|
20
26
|
|
|
21
27
|
result = case detect_type(number)
|
|
22
|
-
when :float then to_words_fractional(number, locale, feminine, locale_data, style: style)
|
|
28
|
+
when :float then to_words_fractional(number, locale, feminine, locale_data, style: style, joiner: joiner)
|
|
23
29
|
when :integer then to_words_integer(number, locale, feminine, locale_data)
|
|
24
|
-
when :datetime then to_words_datetime(number, locale, locale_data, format: date_format, only: type_only, short: type_short)
|
|
25
|
-
when :date then to_words_date(number, locale, locale_data, format: date_format)
|
|
30
|
+
when :datetime then to_words_datetime(number, locale, locale_data, format: date_format, only: type_only, short: type_short, date_case: date_case)
|
|
31
|
+
when :date then to_words_date(number, locale, locale_data, format: date_format, date_case: date_case)
|
|
26
32
|
when :time then to_words_time(number, locale, locale_data, short: type_short)
|
|
27
33
|
else nil
|
|
28
34
|
end
|
|
@@ -36,6 +42,9 @@ module Num2words
|
|
|
36
42
|
locale = args.first.is_a?(Symbol) ? args.first : opts[:locale] || I18n.default_locale
|
|
37
43
|
word_case = opts[:word_case] || :downcase
|
|
38
44
|
currency = (opts[:code] || Num2words.default_currency(locale)).to_s.upcase.to_sym
|
|
45
|
+
minor = opts[:minor] || :always
|
|
46
|
+
|
|
47
|
+
validate_option!(:minor, minor, %i[always nonzero never])
|
|
39
48
|
|
|
40
49
|
unless Num2words.available_currencies(locale).include?(currency)
|
|
41
50
|
warn I18n.t("num2words.warnings.currency_not_available",
|
|
@@ -46,22 +55,44 @@ module Num2words
|
|
|
46
55
|
currency_data = I18n.t("num2words.currencies.#{currency}", locale: locale) or
|
|
47
56
|
raise ArgumentError, "Currency #{currency} not defined in locale #{locale}"
|
|
48
57
|
|
|
49
|
-
|
|
58
|
+
decimal_amount = decimal_currency_amount(amount)
|
|
59
|
+
major_value, minor_value = format('%.2f', decimal_amount.abs).split('.').map(&:to_i)
|
|
50
60
|
|
|
51
61
|
parts = [
|
|
52
62
|
to_words(major_value, locale: locale),
|
|
53
|
-
pluralize(major_value, *currency_data[:major_unit])
|
|
54
|
-
to_words(minor_value, locale: locale, feminine: true),
|
|
55
|
-
pluralize(minor_value, *currency_data[:minor_unit])
|
|
63
|
+
pluralize(major_value, *currency_data[:major_unit])
|
|
56
64
|
]
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
include_minor = minor == :always || (minor == :nonzero && minor_value.positive?)
|
|
67
|
+
if include_minor
|
|
68
|
+
parts.concat([
|
|
69
|
+
to_words(minor_value, locale: locale, feminine: true),
|
|
70
|
+
pluralize(minor_value, *currency_data[:minor_unit])
|
|
71
|
+
])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
parts.unshift(Locales[locale]::GRAMMAR[:minus] || "minus") if decimal_amount.negative?
|
|
59
75
|
|
|
60
76
|
apply_case(parts.join(" ").strip, word_case)
|
|
61
77
|
end
|
|
62
78
|
|
|
63
79
|
private
|
|
64
80
|
|
|
81
|
+
def validate_option!(name, value, allowed_values)
|
|
82
|
+
return if allowed_values.include?(value)
|
|
83
|
+
|
|
84
|
+
raise ArgumentError, "Unsupported #{name} option: #{value.inspect}"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def decimal_currency_amount(amount)
|
|
88
|
+
return amount if amount.is_a?(BigDecimal)
|
|
89
|
+
|
|
90
|
+
normalized_amount = amount.is_a?(String) ? amount.tr(",", ".") : amount.to_s
|
|
91
|
+
BigDecimal(normalized_amount)
|
|
92
|
+
rescue ArgumentError
|
|
93
|
+
raise ArgumentError, "Unsupported currency amount: #{amount.inspect}"
|
|
94
|
+
end
|
|
95
|
+
|
|
65
96
|
def pluralize(number, singular, few, plural)
|
|
66
97
|
number = number.abs
|
|
67
98
|
return plural if (11..14).include?(number % 100)
|
|
@@ -94,15 +125,17 @@ module Num2words
|
|
|
94
125
|
words.compact
|
|
95
126
|
end
|
|
96
127
|
|
|
97
|
-
def to_words_fractional(number, locale, feminine, locale_data, style: :fraction)
|
|
128
|
+
def to_words_fractional(number, locale, feminine, locale_data, style: :fraction, joiner: :default)
|
|
98
129
|
minus_word = locale_data::GRAMMAR[:minus] || "minus"
|
|
99
|
-
conjunction_word = locale_data::GRAMMAR[:conjunction] || "and"
|
|
130
|
+
conjunction_word = joiner.to_sym == :and ? "и" : locale_data::GRAMMAR[:conjunction] || "and"
|
|
100
131
|
default_fraction = locale_data::GRAMMAR[:default_fraction] || "parts"
|
|
101
132
|
fractions_data = locale_data::FRACTIONS || {}
|
|
102
133
|
|
|
103
|
-
|
|
134
|
+
negative = number.is_a?(String) ? number.start_with?("-") : number.negative?
|
|
135
|
+
sign_word = negative ? minus_word : ""
|
|
104
136
|
|
|
105
|
-
|
|
137
|
+
absolute_number = number.is_a?(String) ? number.sub(/\A-/, "").tr(",", ".") : number.abs.to_s
|
|
138
|
+
integer_string, fraction_string = absolute_number.split('.', 2)
|
|
106
139
|
integer_value = integer_string.to_i
|
|
107
140
|
|
|
108
141
|
return to_words_integer(integer_value, locale, feminine, locale_data) if fraction_string.to_i.zero?
|
|
@@ -130,6 +163,10 @@ module Num2words
|
|
|
130
163
|
def to_words_integer(number, locale, feminine, locale_data)
|
|
131
164
|
integer_value = Integer(number)
|
|
132
165
|
|
|
166
|
+
minus_word = locale_data::GRAMMAR[:minus] || "minus"
|
|
167
|
+
negative = integer_value.negative?
|
|
168
|
+
integer_value = integer_value.abs
|
|
169
|
+
|
|
133
170
|
return (feminine ? locale_data::ONES_FEM[0] : locale_data::ONES_MASC[0]) if integer_value.zero?
|
|
134
171
|
|
|
135
172
|
groups = integer_value.to_s
|
|
@@ -143,10 +180,11 @@ module Num2words
|
|
|
143
180
|
words.concat triple_to_words(group_value, scale_index, locale_data, feminine: group_feminine)
|
|
144
181
|
end
|
|
145
182
|
|
|
183
|
+
words.unshift(minus_word) if negative
|
|
146
184
|
words.join(" ")
|
|
147
185
|
end
|
|
148
186
|
|
|
149
|
-
def to_words_date(date, locale, locale_data, format: :default)
|
|
187
|
+
def to_words_date(date, locale, locale_data, format: :default, date_case: :default)
|
|
150
188
|
date = Date.parse(date.to_s) unless date.is_a?(Date)
|
|
151
189
|
|
|
152
190
|
day, month, year = [date.day, date.month, date.year]
|
|
@@ -159,7 +197,8 @@ module Num2words
|
|
|
159
197
|
raise ArgumentError, "Months not found for locale #{locale}" unless months
|
|
160
198
|
raise ArgumentError, "Template not found for locale #{locale}" unless template
|
|
161
199
|
|
|
162
|
-
|
|
200
|
+
day_gender = date_case.to_sym == :genitive ? :masculine : :neuter
|
|
201
|
+
day_words = to_words_ordinal(day, locale, format, locale_data, gender: day_gender)
|
|
163
202
|
month_words = months[month - 1]
|
|
164
203
|
year_words = to_words_ordinal(year, locale, format, locale_data)
|
|
165
204
|
|
|
@@ -173,7 +212,7 @@ module Num2words
|
|
|
173
212
|
gender_data = ordinals[gender] || ordinals[:masculine]
|
|
174
213
|
raise ArgumentError, "Gender #{gender} not found for locale #{locale}, format #{format}" unless gender_data
|
|
175
214
|
|
|
176
|
-
return gender_data[value - 1] if gender_data
|
|
215
|
+
return gender_data[value - 1] if value.between?(1, gender_data.length)
|
|
177
216
|
|
|
178
217
|
if value > 31
|
|
179
218
|
thousands = (value / 100) * 100
|
|
@@ -228,13 +267,13 @@ module Num2words
|
|
|
228
267
|
end
|
|
229
268
|
end
|
|
230
269
|
|
|
231
|
-
def to_words_datetime(datetime, locale, locale_data, format: :default, only: nil, short: false)
|
|
270
|
+
def to_words_datetime(datetime, locale, locale_data, format: :default, only: nil, short: false, date_case: :default)
|
|
232
271
|
datetime = DateTime.parse(datetime) if datetime.is_a?(String)
|
|
233
272
|
|
|
234
273
|
date_format = short && only == :date ? :short : format
|
|
235
274
|
time_format = short && only == :time ? :short : :default
|
|
236
275
|
|
|
237
|
-
date_part = to_words_date(datetime.to_date, locale, locale_data, format: date_format)
|
|
276
|
+
date_part = to_words_date(datetime.to_date, locale, locale_data, format: date_format, date_case: date_case)
|
|
238
277
|
time_part = to_words_time(datetime.to_time, locale, locale_data, format: time_format, short: short)
|
|
239
278
|
|
|
240
279
|
return date_part if only == :date
|
|
@@ -260,12 +299,12 @@ module Num2words
|
|
|
260
299
|
case value
|
|
261
300
|
when Integer then :integer
|
|
262
301
|
when Float then :float
|
|
302
|
+
when DateTime then :datetime
|
|
263
303
|
when Date then :date
|
|
264
304
|
when Time then :time
|
|
265
|
-
when DateTime then :datetime
|
|
266
305
|
when String
|
|
267
306
|
return :integer if value.match?(/\A-?\d+\z/)
|
|
268
|
-
return :float if value.match?(/\A-?\d
|
|
307
|
+
return :float if value.match?(/\A-?\d+[\.,]\d+\z/)
|
|
269
308
|
return :time if value.match?(/\A\d{1,2}:\d{2}(:\d{2})?\z/)
|
|
270
309
|
|
|
271
310
|
# Форматы даты
|
data/lib/num2words/version.rb
CHANGED
data/num2words.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,34 +1,35 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: num2words
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ruslan Fedotov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-05-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: i18n
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: '1.8'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '1.8'
|
|
27
27
|
description: Converts integers and amounts to Russian words with proper gender and
|
|
28
28
|
plural forms.
|
|
29
29
|
email:
|
|
30
30
|
- progruson@gmail.com
|
|
31
|
-
executables:
|
|
31
|
+
executables:
|
|
32
|
+
- num2words-console
|
|
32
33
|
extensions: []
|
|
33
34
|
extra_rdoc_files: []
|
|
34
35
|
files:
|
|
@@ -90,8 +91,10 @@ files:
|
|
|
90
91
|
- config/locales/ur.yml
|
|
91
92
|
- config/locales/vi.yml
|
|
92
93
|
- config/locales/zh.yml
|
|
94
|
+
- exe/num2words-console
|
|
93
95
|
- lib/num2words.rb
|
|
94
96
|
- lib/num2words/config.rb
|
|
97
|
+
- lib/num2words/console.rb
|
|
95
98
|
- lib/num2words/converter.rb
|
|
96
99
|
- lib/num2words/core_ext.rb
|
|
97
100
|
- lib/num2words/i18n.rb
|
|
@@ -170,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
170
173
|
- !ruby/object:Gem::Version
|
|
171
174
|
version: '0'
|
|
172
175
|
requirements: []
|
|
173
|
-
rubygems_version: 3.1.
|
|
176
|
+
rubygems_version: 3.1.2
|
|
174
177
|
signing_key:
|
|
175
178
|
specification_version: 4
|
|
176
179
|
summary: Russian number-to-words with currency (руб/коп) and correct declensions
|