thainum 0.3.0 copy "thainum: ^0.3.0" to clipboard
thainum: ^0.3.0 copied to clipboard

A comprehensive Thai number toolkit: Thai numerals, number-to-words, baht text, formatting, Thai dates and times, and reverse parsing of Thai words to numbers.

thainum #

pub package CI

ชุดเครื่องมือจัดการตัวเลขภาษาไทยแบบครบวงจรสำหรับภาษา Dart — เลขไทย, อ่านเป็นคำ, บาทตัวอักษร, จัดรูปแบบ และแปลงคำกลับเป็นตัวเลข

A comprehensive Thai number toolkit for Dart — Thai numerals, number-to-words, baht text, formatting, Thai dates/times, and (uniquely) reverse parsing of Thai words back into numbers.

Pure Dart, MIT-licensed, no Flutter and no intl dependency (the Thai tables are bundled). A faithful port of go-thainum.

dart pub add thainum

Reverse parsing — words back into numbers (the flagship) #

Essentially nothing else turns Thai words back into numbers. thainum does:

import 'package:thainum/thainum.dart';

parseInt('ยี่สิบเอ็ด');                       // 21
parseInt('หนึ่งร้อยเอ็ด');                     // 101  (เอ็ด form)
parseInt('หนึ่งร้อยหนึ่ง');                    // 101  (หนึ่ง form — both accepted)
parseInt('๒๑');                               // 21   (Thai digits)
parseBaht('ยี่สิบเอ็ดบาทยี่สิบเอ็ดสตางค์');   // 2121 (satang)
parseBigInt('หนึ่งล้านล้านล้าน');             // 10^18

// Stacked ล้าน is handled correctly:
parseBigInt('หนึ่งล้านล้าน');                 // 10^12

All parse failures throw ThaiNumException, which implements FormatException:

try {
  parseInt('สิบสิบ'); // ascending/repeat place is invalid
} on FormatException catch (e) {
  print(e); // ThaiNumException: thainum: misplaced place word ("สิบ")
}

Non-throwing parsing — tryParse* (v0.3.0+) #

When you would rather branch on a null than catch a FormatException, every parser has a tryParse* sibling (and matching String extension):

tryParseInt('ยี่สิบเอ็ด');  // 21
tryParseInt('สิบสิบ');      // null   (invalid → no throw)
tryParseBigInt('หนึ่งล้านล้าน'); // 10^12
tryParseBaht('ยี่สิบเอ็ดบาทยี่สิบเอ็ดสตางค์'); // 2121
tryParseDate('5 มิถุนายน 2567'); // DateTime.utc(2024, 6, 5)

'สิบสิบ'.tryParseThaiInt(); // null

Read digits one by one — speakDigits (อ่านเรียงตัว, v0.3.0+) #

Phone numbers, account numbers and PINs are read digit-by-digit, not as a quantity:

speakDigits('2566');         // 'สอง ห้า หก หก'
speakDigits('081-234-5678'); // 'ศูนย์ แปด หนึ่ง สอง สาม สี่ ห้า หก เจ็ด แปด'
'0812345678'.speakThaiDigits(); // same as above

// Thai numerals accepted; punctuation collapses to one separator.
speakDigits('๒๕๖๖');                          // 'สอง ห้า หก หก'
speakDigits('2566', colloquialTwo: true);     // 'โท ห้า หก หก'  (2 → โท)
speakDigits('2566', separator: '-');          // 'สอง-ห้า-หก-หก'

Thai numeral output — the thaiDigits: flag (v0.3.0+) #

The formatters and date helpers take an optional thaiDigits: flag. When true only the digits become Thai numerals — commas, the decimal point, the ฿ symbol, the - sign and labels like พ.ศ. stay ASCII:

formatInt(1234567, thaiDigits: true); // '๑,๒๓๔,๕๖๗'
formatThb(2121, thaiDigits: true);    // '฿๒๑.๒๑'
formatDateFull(d, thaiDigits: true);  // 'วันพุธที่ ๕ มิถุนายน พ.ศ. ๒๕๖๗'

1234567.toThousandsString(thaiDigits: true);  // '๑,๒๓๔,๕๖๗'
const Satang(2121).toThb(thaiDigits: true);   // '฿๒๑.๒๑'
d.toThaiDate(thaiDigits: true);               // '๕ มิถุนายน ๒๕๖๗'

The default (thaiDigits: false) output is byte-identical to previous releases.

Receiver-style API (v0.2.0+) #

Every top-level function below is also available as an extension method on its receiver type, so the same calls read naturally in a chain. The extensions are exported by the same import 'package:thainum/thainum.dart'; — no extra import needed.

21.toThaiWords();                      // 'ยี่สิบเอ็ด'
'101'.toThaiDigits();                  // '๑๐๑'
1234567.toThousandsString();           // '1,234,567'
'ยี่สิบเอ็ด'.parseThaiInt();           // 21

const Baht(100).toBahtText();          // 'หนึ่งร้อยบาทถ้วน'
const Satang(2121).toBahtText();       // 'ยี่สิบเอ็ดบาทยี่สิบเอ็ดสตางค์'
const Satang(2121).toThb();            // '฿21.21'

final d = DateTime.utc(2024, 6, 5);
d.toThaiDateFull();                    // 'วันพุธที่ 5 มิถุนายน พ.ศ. 2567'
d.buddhistYear;                        // 2567   (getter — property)

The Baht / Satang / BahtBigInt / SatangBigInt wrappers make the money unit a compile-time guarantee: a satang amount can never be passed where baht is expected. int.toBahtText() (and the BigInt / double versions) interpret the receiver as whole baht — the unambiguous default.

The function API (spell(21), baht(100), parseInt(...)) keeps working unchanged.

Features #

  • Thai numeralstoThaiDigits / toArabicDigits (101๑๐๑).
  • Spell numbers as Thai wordsint, BigInt, and decimals, correct to ล้านล้าน (10¹²) and beyond.
  • Baht text (บาทตัวอักษร) — render currency amounts as the formal Thai spelling used on cheques and invoices.
  • Formatting — thousands separators, satang-to-decimal, and a ฿ display.
  • Reverse parsing — turn Thai words back into numbers and satang.
  • Ordinals, fractions & Buddhist-Era yearsordinal (ที่…), fraction (เศษ…ส่วน…), year (พุทธศักราช…), plus ceToBe / beToCe.
  • Thai dates — Thai month/weekday names, Buddhist-Era year, three formatters, and parseDate to turn a Thai date string back into a DateTime.
  • Thai time & durationsformatTime (formal นาฬิกา), formatClock (colloquial ตี / โมง / ทุ่ม), and formatDuration.
  • Money is exact — amounts are handled in integer satang (1 baht = 100 satang) or BigInt, never double. A clearly-labelled lossy float entry point exists for convenience.
  • EtMode — choose between the Royal-Institute-recommended เอ็ด form and the plain หนึ่ง form for trailing ones.

Quick start #

Thai numerals #

toThaiDigits('101');   // ๑๐๑
toArabicDigits('๑๐๑'); // 101

Spell numbers as Thai words #

spell(21);  // ยี่สิบเอ็ด
spell(101); // หนึ่งร้อยเอ็ด
spellBigInt(BigInt.parse('1000000000000')); // หนึ่งล้านล้าน
spellDecimal('12.34'); // สิบสองจุดสามสี่

Baht text (บาทตัวอักษร) #

baht takes an amount in baht (the usual unit); use bahtSatang for sub-baht precision (1 baht = 100 satang), or bahtFromString for a decimal string:

baht(100);                // หนึ่งร้อยบาทถ้วน  (100 baht)
baht(0);                  // ศูนย์บาทถ้วน
bahtSatang(2121);         // ยี่สิบเอ็ดบาทยี่สิบเอ็ดสตางค์ (21.21 baht)
bahtSatang(25);           // ยี่สิบห้าสตางค์
bahtFromString('21.21');  // ยี่สิบเอ็ดบาทยี่สิบเอ็ดสตางค์ (string-exact)

There is also bahtFromDouble(double) (and the satangFromFloat helper) for convenience, but it is lossy — prefer satang or strings for anything that must be exact.

Formatting #

formatInt(1234567); // 1,234,567
formatSatang(2121); // 21.21
formatThb(2121);    // ฿21.21

Ordinals, fractions, and Buddhist-Era years #

ordinal(21);    // ที่ยี่สิบเอ็ด
fraction(3, 4); // เศษสามส่วนสี่
year(2566);     // พุทธศักราชสองพันห้าร้อยหกสิบหก
ceToBe(2023);   // 2566

Thai dates (เดือนไทย / วันไทย / ปี พ.ศ.) #

final d = DateTime.utc(2024, 6, 5);
formatDate(d);     // 5 มิถุนายน 2567
formatDateAbbr(d); // 5 มิ.ย. 2567
formatDateFull(d); // วันพุธที่ 5 มิถุนายน พ.ศ. 2567
monthTh(6);        // มิถุนายน
weekdayTh(d);      // วันพุธ
buddhistYear(d);   // 2567

parseDate('วันพุธที่ 5 มิถุนายน พ.ศ. 2567'); // DateTime.utc(2024, 6, 5)

Dates use the Buddhist-Era year (Gregorian + 543). Wrap a formatted string with toThaiDigits if you want Thai numerals (e.g. ๕ มิถุนายน ๒๕๖๗).

Note: Dart's DateTime.weekday is Monday=1 .. Sunday=7. thainum maps that internally to the correct Thai weekday name, so weekdayTh(DateTime) just works.

Time of day and durations #

final t = DateTime.utc(2024, 1, 1, 14, 30);
formatTime(t);  // สิบสี่นาฬิกาสามสิบนาที (formal)
formatClock(t); // บ่ายสองโมงครึ่ง (colloquial)
formatDuration(const Duration(minutes: 90)); // หนึ่งชั่วโมงสามสิบนาที

EtMode — เอ็ด vs หนึ่ง #

By default the library uses EtMode.always, the Royal-Institute-recommended form where a trailing one is read เอ็ด. Use EtMode.tensOnly if you want a trailing one to read หนึ่ง except in the tens place:

const plain = Speller(et: EtMode.tensOnly);
spell(101);         // หนึ่งร้อยเอ็ด   (default EtMode.always)
plain.spellInt(101); // หนึ่งร้อยหนึ่ง

Speller exposes .spellInt, .spellBigInt, .spellDecimal, .baht, .ordinal, .fraction, and .year, so you can pick the EtMode once and reuse it. Reverse parsing accepts both forms.

A note on money and precision #

Money is handled in integer satang (1 baht = 100 satang) or BigInt, never double. This means there are no binary-floating-point rounding surprises in your baht text. The *FromFloat / *FromDouble entry points are provided only as a convenience and are documented as lossy — reach for the satang / string / BigInt APIs whenever correctness matters.

License #

MIT © 2026 MaIII (ultramcu)

0
likes
0
points
354
downloads

Publisher

verified publisher10v3n4m.cc

Weekly Downloads

A comprehensive Thai number toolkit: Thai numerals, number-to-words, baht text, formatting, Thai dates and times, and reverse parsing of Thai words to numbers.

Repository (GitHub)
View/report issues

Topics

#thai #number-to-words #baht #i18n #intl

License

unknown (license)

More

Packages that depend on thainum