uae-gold-calculator 1.0.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +79 -0
- data/exe/uae-gold-calculator +48 -0
- data/lib/uae_gold_calculator.rb +113 -0
- metadata +51 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a7d280f92d142e15ab21616135e1ca094a384cbcf3503a4ca9f4d63ed62e7704
|
|
4
|
+
data.tar.gz: 3c443bccbe540f53e87067b0421150222a492b437b5d92ec35226f439b1f1d7d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0576f2eb658146d1700e9eb393957cef924c85250d2ed5f3187b49a45f3705f3d24c1bf175571704e37ed29a423a98decd09da7a8b0d379498acd175ab786a45
|
|
7
|
+
data.tar.gz: b052de66bce06d27c3544e3fd65c7f279481cca3fe67bc7a7c8f99bcc576e6e53526a82653e5940bcec6a0fc2e410844aadd24f8ee29fe5745bc47a9a25a4c1f
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 UAE Gold Prices (https://uaegoldprices.ae/)
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# uae-gold-calculator
|
|
2
|
+
|
|
3
|
+
Gold value calculator for the UAE market. Give it today's 24K price per gram and it works out every karat, any weight unit, the making charge, 5% VAT and zakat, in Arabic or English. No network calls, no dependencies.
|
|
4
|
+
|
|
5
|
+
- **Karat table**: 24K, 22K, 21K, 18K and 14K per gram, per tola and per troy ounce using the fineness UAE price boards quote: 24K 999, 22K 914, 21K 874, 18K 749, 14K 583 (karat price = 24K price × fineness ÷ 999).
|
|
6
|
+
- **Units**: gram, kilogram, troy ounce (31.1034768 g), tola (11.6638038 g) and mithqal (4.25 g). Arabic unit names such as `جرام`, `أونصة`, `تولة`, `مثقال` work too.
|
|
7
|
+
- **Jewellery price**: metal value + making charge (AED per gram, percent of metal, or a fixed amount) + VAT on both, the way UAE shops bill it.
|
|
8
|
+
- **Zakat**: adds up pure gold across items, compares it with the 85 g nisab and returns 2.5% of the value when due.
|
|
9
|
+
- **Friendly input**: `461.11`, `461,11`, `14,342.21` and Arabic-Indic `٤٦١٫١١` all parse.
|
|
10
|
+
- **Arabic and English** CLI output (`--lang ar`).
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
gem install uae-gold-calculator
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Library
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
require "uae_gold_calculator"
|
|
22
|
+
G = UaeGoldCalculator
|
|
23
|
+
|
|
24
|
+
G.price_table(461.11)[2][:per_gram] # => 403.41 (21K)
|
|
25
|
+
G.item_price(price24: 461.11, weight: 10, karat: 21, making: 30)[:total] # => 4550.84
|
|
26
|
+
G.zakat(461.11, [{ weight: 100, karat: 21 }])[:zakat] # => 1008.53
|
|
27
|
+
G.parse_number("٤٦١٫١١") # => 461.11
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## CLI
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
$ uae-gold-calculator table --price 461.11
|
|
34
|
+
Karat Per gram Per tola Per ounce
|
|
35
|
+
24K (999) 461.11 5378.30 14342.12
|
|
36
|
+
22K (914) 421.88 4920.68 13121.82
|
|
37
|
+
21K (874) 403.41 4705.34 12547.56
|
|
38
|
+
18K (749) 345.72 4032.38 10753.00
|
|
39
|
+
14K (583) 269.10 3138.69 8369.83
|
|
40
|
+
|
|
41
|
+
$ uae-gold-calculator item --price 461.11 --weight 10 --karat 21 --making 30 --lang ar
|
|
42
|
+
قيمة الذهب: 4034.14 د.إ
|
|
43
|
+
المصنعية: 300.00 د.إ
|
|
44
|
+
ضريبة القيمة المضافة (5%): 216.71 د.إ
|
|
45
|
+
الإجمالي: 4550.84 د.إ
|
|
46
|
+
|
|
47
|
+
$ uae-gold-calculator convert 2 tola g
|
|
48
|
+
23.3276
|
|
49
|
+
|
|
50
|
+
$ uae-gold-calculator zakat --price 461.11 --weight 100 --karat 21
|
|
51
|
+
Zakat due: 1008.53 AED
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Options for `item`: `--unit g|kg|oz|tola|mithqal`, `--karat`, `--making`, `--making-type per_gram|percent|fixed`, `--vat 0.05` (use `--vat 0` for investment bars, which are zero-rated in the UAE).
|
|
55
|
+
|
|
56
|
+
## How it calculates
|
|
57
|
+
|
|
58
|
+
| Step | Formula |
|
|
59
|
+
|---|---|
|
|
60
|
+
| Karat price per gram | `price24 × fineness / 999` (24K 999, 22K 914, 21K 874, 18K 749, 16K 666, 14K 583; other karats `karat / 24`) |
|
|
61
|
+
| Metal value | `grams × karat price` |
|
|
62
|
+
| Making charge | `rate × grams`, or `metal × rate / 100`, or a fixed amount |
|
|
63
|
+
| VAT | `(metal + making) × 5%` |
|
|
64
|
+
| Zakat | `24K-equivalent grams = Σ grams × purity`; due when ≥ 85 g; `2.5% × pure grams × price24` |
|
|
65
|
+
|
|
66
|
+
Amounts are rounded half away from zero to 2 decimals on output only. Results are estimates: shop prices, VAT treatment of investment gold and zakat rulings vary, so check with your jeweller or scholar.
|
|
67
|
+
|
|
68
|
+
## بالعربية
|
|
69
|
+
|
|
70
|
+
حاسبة لقيمة الذهب في الإمارات: أدخل سعر جرام الذهب عيار 24 اليوم لتحصل على أسعار عيارات 24 و22 و21 و18 و14 بالجرام والتولة والأونصة، وسعر قطعة المجوهرات مع المصنعية وضريبة القيمة المضافة 5%، وحساب زكاة الذهب حسب نصاب 85 جرامًا. تقبل الأرقام العربية مثل ٤٦١٫١١ وأسماء الوحدات بالعربية، وتعمل دون اتصال بالإنترنت.
|
|
71
|
+
|
|
72
|
+
## Links
|
|
73
|
+
|
|
74
|
+
- Live UAE gold rates: [سعر الذهب اليوم في الامارات](https://uaegoldprices.ae/)
|
|
75
|
+
- Source code: https://github.com/nbkdevs/uae-gold-prices
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT © UAE Gold Prices
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "uae_gold_calculator"
|
|
5
|
+
|
|
6
|
+
G = UaeGoldCalculator
|
|
7
|
+
pos = []
|
|
8
|
+
opt = {}
|
|
9
|
+
i = 0
|
|
10
|
+
while i < ARGV.length
|
|
11
|
+
if ARGV[i].start_with?("--")
|
|
12
|
+
opt[ARGV[i][2..]] = ARGV[i + 1]
|
|
13
|
+
i += 2
|
|
14
|
+
else
|
|
15
|
+
pos << ARGV[i]
|
|
16
|
+
i += 1
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
ar = opt["lang"] == "ar"
|
|
20
|
+
cur = ar ? "د.إ" : "AED"
|
|
21
|
+
begin
|
|
22
|
+
case pos.first
|
|
23
|
+
when "convert"
|
|
24
|
+
puts G.round_money(G.convert(pos[1], pos[2], pos[3]), 4)
|
|
25
|
+
when "table"
|
|
26
|
+
puts(ar ? "العيار\tسعر الجرام\tسعر التولة\tسعر الأونصة" : "Karat\tPer gram\tPer tola\tPer ounce")
|
|
27
|
+
G.price_table(opt.fetch("price")).each do |r|
|
|
28
|
+
puts format("%dK (%d)\t%.2f\t%.2f\t%.2f", r[:karat], r[:hallmark], r[:per_gram], r[:per_tola], r[:per_ounce])
|
|
29
|
+
end
|
|
30
|
+
when "item"
|
|
31
|
+
r = G.item_price(price24: opt.fetch("price"), weight: opt.fetch("weight"), unit: opt.fetch("unit", "g"),
|
|
32
|
+
karat: G.parse_number(opt.fetch("karat", "24")), making: opt.fetch("making", "0"),
|
|
33
|
+
making_type: opt.fetch("making-type", "per_gram"), vat_rate: opt.fetch("vat", "0.05"))
|
|
34
|
+
puts format("%s: %.2f %s", ar ? "قيمة الذهب" : "Gold value", r[:metal], cur)
|
|
35
|
+
puts format("%s: %.2f %s", ar ? "المصنعية" : "Making charge", r[:making], cur)
|
|
36
|
+
puts format("%s: %.2f %s", ar ? "ضريبة القيمة المضافة" : "VAT", r[:vat], cur)
|
|
37
|
+
puts format("%s: %.2f %s", ar ? "الإجمالي" : "Total", r[:total], cur)
|
|
38
|
+
when "zakat"
|
|
39
|
+
z = G.zakat(opt.fetch("price"), [{ weight: opt.fetch("weight"), unit: opt.fetch("unit", "g"),
|
|
40
|
+
karat: G.parse_number(opt.fetch("karat", "24")) }])
|
|
41
|
+
puts(z[:due] ? format("%s: %.2f %s", ar ? "الزكاة المستحقة" : "Zakat due", z[:zakat], cur) : (ar ? "أقل من النصاب: لا زكاة" : "Below nisab: no zakat due"))
|
|
42
|
+
else
|
|
43
|
+
puts "uae-gold-calculator #{G::VERSION}: table | item | convert | zakat. Today's 24K price: https://uaegoldprices.ae/"
|
|
44
|
+
end
|
|
45
|
+
rescue KeyError, ArgumentError => e
|
|
46
|
+
warn "Error: #{e.message}"
|
|
47
|
+
exit 1
|
|
48
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Gold value maths for the UAE market: karat prices, unit conversion, making
|
|
4
|
+
# charges, VAT and zakat. Pure Ruby, no network. Pass today's 24K price per
|
|
5
|
+
# gram (for example from https://uaegoldprices.ae/).
|
|
6
|
+
module UaeGoldCalculator
|
|
7
|
+
VERSION = "1.0.0"
|
|
8
|
+
KARATS = [24, 22, 21, 18, 14].freeze
|
|
9
|
+
# Fineness per mille used by UAE gold price boards (and uaegoldprices.ae).
|
|
10
|
+
# A karat's price = 24K price x fineness / 999; other karats use karat / 24.
|
|
11
|
+
HALLMARKS = { 24 => 999, 22 => 914, 21 => 874, 18 => 749, 16 => 666, 14 => 583 }.freeze
|
|
12
|
+
UNITS = { "g" => 1.0, "kg" => 1000.0, "oz" => 31.1034768, "tola" => 11.6638038, "mithqal" => 4.25 }.freeze
|
|
13
|
+
ALIASES = {
|
|
14
|
+
"gram" => "g", "grams" => "g", "gr" => "g", "جرام" => "g", "غرام" => "g",
|
|
15
|
+
"kilogram" => "kg", "kilo" => "kg", "كيلو" => "kg",
|
|
16
|
+
"ounce" => "oz", "ozt" => "oz", "troy_ounce" => "oz", "troy-ounce" => "oz", "أونصة" => "oz", "اونصة" => "oz",
|
|
17
|
+
"tolas" => "tola", "تولة" => "tola", "mithqals" => "mithqal", "misqal" => "mithqal", "مثقال" => "mithqal"
|
|
18
|
+
}.freeze
|
|
19
|
+
UAE_VAT_RATE = 0.05
|
|
20
|
+
NISAB_GRAMS = 85.0
|
|
21
|
+
ZAKAT_RATE = 0.025
|
|
22
|
+
|
|
23
|
+
module_function
|
|
24
|
+
|
|
25
|
+
# Round half away from zero.
|
|
26
|
+
def round_money(x, dp = 2)
|
|
27
|
+
f = 10.0**dp
|
|
28
|
+
v = ((x.abs * f) + 1e-9).round / f
|
|
29
|
+
x.negative? ? -v : v
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Parse "461.11", "461,11", "14,342.21" or Arabic-Indic "٤٦١٫١١".
|
|
33
|
+
def parse_number(value)
|
|
34
|
+
return value.to_f if value.is_a?(Numeric)
|
|
35
|
+
|
|
36
|
+
s = value.to_s.strip.tr("٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹٫", "01234567890123456789.").delete("٬").gsub(/\s/, "")
|
|
37
|
+
s = s.match?(/\A\d{1,3}(,\d{3})+(\.\d+)?\z/) ? s.delete(",") : s.sub(",", ".")
|
|
38
|
+
Float(s)
|
|
39
|
+
rescue ArgumentError, TypeError
|
|
40
|
+
raise ArgumentError, "not a number: #{value}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def normalize_unit(unit)
|
|
44
|
+
u = (unit || "g").to_s.strip.downcase
|
|
45
|
+
k = ALIASES.fetch(u, u)
|
|
46
|
+
raise ArgumentError, "unknown unit: #{unit}. Use g, kg, oz, tola or mithqal" unless UNITS.key?(k)
|
|
47
|
+
|
|
48
|
+
k
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def check(name, v, allow_zero: false)
|
|
52
|
+
if !v.finite? || v.negative? || (!allow_zero && v.zero?)
|
|
53
|
+
raise ArgumentError, "#{name} must be #{allow_zero ? 'non-negative' : 'positive'}"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
v
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def purity(karat)
|
|
60
|
+
k = karat.to_f
|
|
61
|
+
raise ArgumentError, "karat must be between 0 and 24" unless k.positive? && k <= 24
|
|
62
|
+
return 1.0 if k == 24
|
|
63
|
+
|
|
64
|
+
f = k == k.floor ? HALLMARKS[k.to_i] : nil
|
|
65
|
+
f ? f / 999.0 : k / 24
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def convert(value, from, to)
|
|
69
|
+
check("value", parse_number(value), allow_zero: true) * UNITS[normalize_unit(from)] / UNITS[normalize_unit(to)]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def karat_price(price24, karat)
|
|
73
|
+
check("price24", parse_number(price24)) * purity(karat)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def price_table(price24)
|
|
77
|
+
KARATS.map do |k|
|
|
78
|
+
g = karat_price(price24, k)
|
|
79
|
+
{ karat: k, hallmark: HALLMARKS[k], per_gram: round_money(g),
|
|
80
|
+
per_tola: round_money(g * UNITS["tola"]), per_ounce: round_money(g * UNITS["oz"]) }
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def item_price(price24:, weight:, unit: "g", karat: 24, making: 0, making_type: :per_gram, vat_rate: UAE_VAT_RATE)
|
|
85
|
+
grams = check("weight", parse_number(weight)) * UNITS[normalize_unit(unit)]
|
|
86
|
+
per_gram = karat_price(price24, karat)
|
|
87
|
+
metal = grams * per_gram
|
|
88
|
+
m = check("making", parse_number(making), allow_zero: true)
|
|
89
|
+
mk = case making_type.to_sym
|
|
90
|
+
when :per_gram then m * grams
|
|
91
|
+
when :percent then metal * m / 100
|
|
92
|
+
when :fixed then m
|
|
93
|
+
else raise ArgumentError, "making_type must be per_gram, percent or fixed"
|
|
94
|
+
end
|
|
95
|
+
rate = check("vat_rate", parse_number(vat_rate), allow_zero: true)
|
|
96
|
+
sub = metal + mk
|
|
97
|
+
{ grams: round_money(grams, 4), price_per_gram: round_money(per_gram), metal: round_money(metal),
|
|
98
|
+
making: round_money(mk), subtotal: round_money(sub), vat_rate: rate, vat: round_money(sub * rate),
|
|
99
|
+
total: round_money(sub + (sub * rate)) }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# items: [{ weight: 100, karat: 21, unit: "g" }]
|
|
103
|
+
def zakat(price24, items)
|
|
104
|
+
p = check("price24", parse_number(price24))
|
|
105
|
+
pure = items.sum do |it|
|
|
106
|
+
check("weight", parse_number(it[:weight]), allow_zero: true) * UNITS[normalize_unit(it[:unit])] * purity(it.fetch(:karat, 24))
|
|
107
|
+
end
|
|
108
|
+
value = pure * p
|
|
109
|
+
due = pure + 1e-9 >= NISAB_GRAMS
|
|
110
|
+
{ pure_grams: round_money(pure, 4), value: round_money(value), nisab_value: round_money(NISAB_GRAMS * p),
|
|
111
|
+
due: due, zakat: due ? round_money(value * ZAKAT_RATE) : 0.0 }
|
|
112
|
+
end
|
|
113
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: uae-gold-calculator
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- UAE Gold Prices
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: 'Price gold in AED from today''s 24K rate: 24/22/21/18/14K per gram,
|
|
13
|
+
tola and troy ounce, making charges (per gram, percent or fixed), 5% VAT and zakat
|
|
14
|
+
against the 85 g nisab. Accepts Arabic-Indic digits and Arabic unit names. Library
|
|
15
|
+
+ CLI, no dependencies.'
|
|
16
|
+
executables:
|
|
17
|
+
- uae-gold-calculator
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- LICENSE
|
|
22
|
+
- README.md
|
|
23
|
+
- exe/uae-gold-calculator
|
|
24
|
+
- lib/uae_gold_calculator.rb
|
|
25
|
+
homepage: https://uaegoldprices.ae/
|
|
26
|
+
licenses:
|
|
27
|
+
- MIT
|
|
28
|
+
metadata:
|
|
29
|
+
homepage_uri: https://uaegoldprices.ae/
|
|
30
|
+
source_code_uri: https://github.com/nbkdevs/uae-gold-prices
|
|
31
|
+
bug_tracker_uri: https://github.com/nbkdevs/uae-gold-prices/issues
|
|
32
|
+
rubygems_mfa_required: 'true'
|
|
33
|
+
rdoc_options: []
|
|
34
|
+
require_paths:
|
|
35
|
+
- lib
|
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '2.7'
|
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
requirements: []
|
|
47
|
+
rubygems_version: 4.0.20
|
|
48
|
+
specification_version: 4
|
|
49
|
+
summary: 'Gold value calculator for the UAE: karat prices, making charges, 5% VAT
|
|
50
|
+
and zakat.'
|
|
51
|
+
test_files: []
|