thai_id_utils 0.1.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 +7 -0
- data/Gemfile +5 -0
- data/README.md +33 -0
- data/Rakefile +9 -0
- data/lib/thai_id_utils/version.rb +5 -0
- data/lib/thai_id_utils.rb +89 -0
- metadata +67 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d9194c3362b9038193a979c13e0d7723bb0c6f0c3ce41ff17523086ef8a04672
|
|
4
|
+
data.tar.gz: dac42ef970424a31999019dc4c3d8d1fa5c5739c55427440906e118d4c2cecba
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c3f92740ba6ac0700b5cddb7abdc23a74cdc759a822a14936a1a36acbd43e021ad42f395889ec09d4db5cf3ed1f641599d454d1b8eb4cc17756365f26f853ab9
|
|
7
|
+
data.tar.gz: 49bbfa319256583fd8156cea558995d2d555e17352b0391830046ff78cdb90034306c9cf5cb0d5eacf13195380d61c3196e14d7d7d27f38b266195b04c67240c
|
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Thai ID Utils
|
|
2
|
+
|
|
3
|
+
Thai ID Utils is a zero-dependency Ruby gem for validating and decoding Thai national ID numbers. It provides a simple API to check the official modulus-11 checksum, extract the embedded components (category, office code, district code, sequence), and get a human-readable description of the category code.
|
|
4
|
+
|
|
5
|
+
Thai ID Utils เป็น Ruby gem ที่ไม่ต้องพึ่งพาไลบรารีเสริม สำหรับตรวจสอบความถูกต้องและถอดรหัสหมายเลขบัตรประชาชนไทย โดยมี API ที่ใช้งานง่ายสำหรับตรวจสอบ checksum ตามมาตรฐาน modulus-11 ดึงส่วนประกอบต่างๆ (ประเภทผู้ลงทะเบียน รหัสหน่วยงาน รหัสอำเภอ และหมายเลขลำดับ) และแสดงคำอธิบายของรหัสประเภทในรูปแบบอ่านง่าย
|
|
6
|
+
|
|
7
|
+
## Usage / วิธีใช้งาน
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
require "thai_id_utils"
|
|
11
|
+
|
|
12
|
+
id = "3012304567082"
|
|
13
|
+
|
|
14
|
+
# ✅ Validate checksum
|
|
15
|
+
if ThaiIdUtils.valid?(id)
|
|
16
|
+
puts "Valid!"
|
|
17
|
+
else
|
|
18
|
+
puts "Invalid ID"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# 🔍 Decode components
|
|
22
|
+
info = ThaiIdUtils.decode(id)
|
|
23
|
+
# => { category: 1, office_code: "6099", district_code: "99", sequence: "00257" }
|
|
24
|
+
puts info.inspect
|
|
25
|
+
|
|
26
|
+
# 🏷️ Get category description
|
|
27
|
+
desc = ThaiIdUtils.category_description(info[:category])
|
|
28
|
+
# => "Thai nationals who were born after 1 January 1984 and had their birth notified within the given deadline (15 days)."
|
|
29
|
+
puts desc
|
|
30
|
+
|
|
31
|
+
# 🎲 Generate a new random valid ID
|
|
32
|
+
new_id = ThaiIdUtils.generate
|
|
33
|
+
puts new_id # => e.g. "3601205234518"
|
data/Rakefile
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# ThaiIdUtils: Validate and decode Thai national ID numbers,
|
|
4
|
+
# providing checksum validation, component decoding, ID generation,
|
|
5
|
+
# and human-readable category descriptions.
|
|
6
|
+
module ThaiIdUtils
|
|
7
|
+
class InvalidIDError < StandardError; end
|
|
8
|
+
|
|
9
|
+
# ----------------------------------------------------------------------------
|
|
10
|
+
# Mapping of category codes to their descriptions
|
|
11
|
+
# ----------------------------------------------------------------------------
|
|
12
|
+
# rubocop:disable Layout/LineLength
|
|
13
|
+
CATEGORY_DESCRIPTIONS = {
|
|
14
|
+
0 => '(Not found on cards of Thai nationals but may be found in the other issued identity cards below)',
|
|
15
|
+
1 => 'Thai nationals who were born after 1 January 1984 and had their birth notified within the given deadline (15 days).',
|
|
16
|
+
2 => 'Thai nationals who were born after 1 January 1984 but failed to have their birth notified in time.',
|
|
17
|
+
3 => 'Thai nationals or foreign nationals with identification cards who were born and whose names were included in a house registration book before 1 January 1984',
|
|
18
|
+
4 => 'Thai nationals who were born before 1 January 1984 but were not included in a house registration book at that time, for example due to moving residences',
|
|
19
|
+
5 => 'Thai nationals who missed the official census or other special cases, for instance those of dual nationality',
|
|
20
|
+
6 => 'Foreign nationals who are living in Thailand temporarily and illegal migrants',
|
|
21
|
+
7 => 'Children of people of category 6 who were born in Thailand',
|
|
22
|
+
8 => 'Foreign nationals who are living in Thailand permanently or Thai nationals by naturalization'
|
|
23
|
+
}.freeze
|
|
24
|
+
# rubocop:enable Layout/LineLength
|
|
25
|
+
|
|
26
|
+
# Public: Validate checksum using Thailand’s modulus-11 algorithm
|
|
27
|
+
def self.valid?(id)
|
|
28
|
+
digits = id.to_s.chars.map(&:to_i)
|
|
29
|
+
return false unless digits.size == 13
|
|
30
|
+
|
|
31
|
+
sum = digits[0..11].each_with_index.sum { |d, i| d * (13 - i) }
|
|
32
|
+
((11 - (sum % 11)) % 10) == digits.last
|
|
33
|
+
rescue StandardError
|
|
34
|
+
false
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Public: Decode components present in a Thai ID
|
|
38
|
+
# Returns a hash with keys:
|
|
39
|
+
# :category => Integer
|
|
40
|
+
# :office_code => String (4-digit registrar)
|
|
41
|
+
# :district_code => String (last 2 of office_code)
|
|
42
|
+
# :sequence => String (5-digit personal sequence)
|
|
43
|
+
def self.decode(id)
|
|
44
|
+
raise InvalidIDError, 'Invalid ID' unless valid?(id)
|
|
45
|
+
|
|
46
|
+
d = id.to_s.chars
|
|
47
|
+
|
|
48
|
+
{
|
|
49
|
+
category: d[0].to_i,
|
|
50
|
+
office_code: d[1..4].join,
|
|
51
|
+
district_code: d[3..4].join,
|
|
52
|
+
sequence: d[5..9].join
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Public: Generate a random, valid 13-digit Thai national ID.
|
|
57
|
+
# You can override any component or let it be randomized.
|
|
58
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
59
|
+
def self.generate(category: rand(1..6),
|
|
60
|
+
office_code: nil,
|
|
61
|
+
district_code: nil,
|
|
62
|
+
sequence: nil)
|
|
63
|
+
# Build and override office_code/district_code
|
|
64
|
+
office_code = format('%04d', office_code || rand(1..9_999))
|
|
65
|
+
office_code[2..3] = district_code.to_s.rjust(2, '0') if district_code
|
|
66
|
+
|
|
67
|
+
# Sequence (5 digits) and classification (2 digits)
|
|
68
|
+
sequence = format('%05d', sequence || rand(0..99_999))
|
|
69
|
+
classification = format('%02d', rand(0..99))
|
|
70
|
+
|
|
71
|
+
# First 12 digits: category + office_code + sequence + classification
|
|
72
|
+
digits = [category.to_i] +
|
|
73
|
+
office_code.chars.map(&:to_i) +
|
|
74
|
+
sequence.chars.map(&:to_i) +
|
|
75
|
+
classification.chars.map(&:to_i)
|
|
76
|
+
|
|
77
|
+
# Checksum
|
|
78
|
+
sum = digits.each_with_index.sum { |d, i| d * (13 - i) }
|
|
79
|
+
check = (11 - (sum % 11)) % 10
|
|
80
|
+
|
|
81
|
+
(digits + [check]).join
|
|
82
|
+
end
|
|
83
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
84
|
+
|
|
85
|
+
# Public: Return a human-readable description for a category code
|
|
86
|
+
def self.category_description(category)
|
|
87
|
+
CATEGORY_DESCRIPTIONS[category.to_i] || 'Unknown category'
|
|
88
|
+
end
|
|
89
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: thai_id_utils
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Chayut Orapinpatipat
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-06-15 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: minitest
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '5.0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '5.0'
|
|
27
|
+
description: |
|
|
28
|
+
Zero-dependency Ruby utilities for:
|
|
29
|
+
• checksum validation (modulus-11),
|
|
30
|
+
• component decoding (category, office_code, district_code, sequence),
|
|
31
|
+
• random valid ID generation,
|
|
32
|
+
• human-readable category descriptions.
|
|
33
|
+
email:
|
|
34
|
+
- chayut_o@hotmail.com
|
|
35
|
+
executables: []
|
|
36
|
+
extensions: []
|
|
37
|
+
extra_rdoc_files: []
|
|
38
|
+
files:
|
|
39
|
+
- Gemfile
|
|
40
|
+
- README.md
|
|
41
|
+
- Rakefile
|
|
42
|
+
- lib/thai_id_utils.rb
|
|
43
|
+
- lib/thai_id_utils/version.rb
|
|
44
|
+
homepage: https://github.com/chayuto/thai-id-utils
|
|
45
|
+
licenses:
|
|
46
|
+
- MIT
|
|
47
|
+
metadata: {}
|
|
48
|
+
post_install_message:
|
|
49
|
+
rdoc_options: []
|
|
50
|
+
require_paths:
|
|
51
|
+
- lib
|
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
53
|
+
requirements:
|
|
54
|
+
- - ">="
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: '2.7'
|
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
requirements: []
|
|
63
|
+
rubygems_version: 3.5.11
|
|
64
|
+
signing_key:
|
|
65
|
+
specification_version: 4
|
|
66
|
+
summary: Validate and decode Thai national ID numbers
|
|
67
|
+
test_files: []
|