Repository: joke2k/faker
Pull request #1321 (2020-11-18 22:45:32)

[th_TH] Add date_time and bank providers
### What does this changes

- Add date_time provider for th_TH locale, with Thai day of week and month names, also Buddhist Era.
- Add bank provider, with swift code dataset
- Update female, male, and nonbinary person names

Test-related (generic, not th_TH specific):
- Add tests for profile, md5, sha1, and sha256 providers
- Add additional tests for generic date_time providers (few combinations of parameters)
- Remove unnecessary hasattr check in hu_HU and ru_RU person providers (the class members they checked for are always presented in those locales)
- Mark `pragma: no cover` for empty en_US profile, python, and user_agent providers

### What was wrong

Previously, there's no date_time and bank providers for th_TH

### How this fixes it

- Implement `thai_strftime()`, a localized strftime()
- Override `date()` and `time()` to use thai_strftime()
  - The new date() and time() have `thai_digit` boolean flag to switch the output between Thai digit (True) and Arabic (False). Default is Arabic.
  - The new date() also has `buddhist_era` boolean flag to switch the output between Buddhist Era and standard AD. Default is Buddhist Era (AD+543).
- Also override `century()` to use regular numbers like 18, 19, 20 (instead of Roman numerals)
  - century() also has thai_digit and buddhist_era boolean flag.
  - When buddhist_era is True, the output will be between 1-25.
  - When buddhist_era is False, the output will be between 1-21.

```
>>> faker.date()
'21 พ.ย. 2537'
>>> faker.date(buddhist_era=False)
'18 พ.ย. 1979'
>>> faker.date(thai_digit=True)
'๒๘ ก.ย. ๒๕๑๕'

>>> faker.time()
'14:28:13'
>>> faker.time(thai_digit=True)
'๑๕:๐๗:๕๖'

>>> faker.century()
'23'
>>> faker.century(buddhist_era=False)
'19'
>>> faker.century(thai_digit=True, buddhist_era=False)
'๒๐'
```

- Add bban format (10 digits) and swift code dataset for bank provider

```
>>> faker.bban()
'6860886113'

>>> faker.iban()
'TH715587648248'

>>> faker.swift(use_dataset=True)
'GSBATHB2'
```

### License

- I'm the author of `thai_strftime()`, which is also available from https://gist.github.com/bact/b8afe49cb1ae62913e6c1e899dcddbdb  as public domain/CC0.
- If it is necessary for maintainability of the code base, I also grant the permission here for the faker project to change the license of this piece of code as the maintainer of faker sees fit (like, change it to MIT License or compatible).


bact: I also change `num_sample_runs` value of filPh's test_date_time from 1,000 to 50, which should be enough for the list of days of week/months with no more than 12 members.

Patch:
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 80b42255..13122ae9 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 4.15.0
+current_version = 4.17.1
 files = VERSION faker/__init__.py docs/conf.py
 commit = True
 tag = True
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1cb973a7..1221350d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,16 @@
 ## Changelog
 
+### [4.17.1 - 2020-11-19](https://github.com/joke2k/faker/compare/v4.17.0...v4.17.1)
+
+* Correct spelling errors in city names for ``de_DE``. Thanks @AnjaGer.
+### [4.17.0 - 2020-11-19](https://github.com/joke2k/faker/compare/v4.16.0...v4.17.0)
+
+* Add name pairs to get matched representation in ``ja_JP`` person provider. Thanks @yu-ichiro.
+
 ### [4.16.0 - 2020-11-17](https://github.com/joke2k/faker/compare/v4.15.0...v4.16.0)
 
 * Add SSN, company name, address, and license plate providers for ``th_TH``. Thanks @bact.
+
 ### [4.15.0 - 2020-11-16](https://github.com/joke2k/faker/compare/v4.14.2...v4.15.0)
 
 * Add postcode format, country names, person prefix weights, and update phone number format for ``th_TH``. Thanks @bact.
diff --git a/README.rst b/README.rst
index e99f40db..ab0620c4 100644
--- a/README.rst
+++ b/README.rst
@@ -170,7 +170,7 @@ Command line usage
 
 When installed, you can invoke faker from the command-line:
 
-.. code:: bash
+.. code:: console
 
     faker [-h] [--version] [-o output]
           [-l {bg_BG,cs_CZ,...,zh_CN,zh_TW}]
@@ -210,7 +210,7 @@ Where:
 
 Examples:
 
-.. code:: bash
+.. code:: console
 
     $ faker address
     968 Bahringer Garden Apt. 722
diff --git a/VERSION b/VERSION
index 5c517bf1..1b0a87fd 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-4.15.0
+4.17.1
diff --git a/docs/conf.py b/docs/conf.py
index a8d2a1fa..48086197 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -51,9 +51,9 @@ copyright = '2014, Daniele Faraglia'
 # built documents.
 #
 # The short X.Y version.
-version = '4.15.0'
+version = '4.17.1'
 # The full version, including alpha/beta/rc tags.
-release = '4.15.0'
+release = '4.17.1'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/faker/__init__.py b/faker/__init__.py
index 3d6f34a8..e507e225 100644
--- a/faker/__init__.py
+++ b/faker/__init__.py
@@ -2,4 +2,4 @@ from faker.factory import Factory  # noqa F401
 from faker.generator import Generator  # noqa F401
 from faker.proxy import Faker  # noqa F401
 
-VERSION = '4.15.0'
+VERSION = '4.17.1'
diff --git a/faker/providers/address/de_DE/__init__.py b/faker/providers/address/de_DE/__init__.py
index f70d5638..fd79ec27 100644
--- a/faker/providers/address/de_DE/__init__.py
+++ b/faker/providers/address/de_DE/__init__.py
@@ -36,7 +36,7 @@ class Provider(AddressProvider):
         'Bersenbrück', 'Biedenkopf', 'Bischofswerda', 'Bitterfeld', 'Bogen',
         'Borken', 'Borna', 'Brand', 'Brandenburg', 'Bremen', 'Bremervörde',
         'Brilon', 'Bruchsal', 'Burg', 'Burgdorf', 'Burglengenfeld',
-        'Böblingen', 'Büsingenm Hochrhein', 'Bützow', 'Calau', 'Calw', 'Celle',
+        'Böblingen', 'Büsingen am Hochrhein', 'Bützow', 'Calau', 'Calw', 'Celle',
         'Chemnitz', 'Cloppenburg', 'Coburg', 'Cottbus', 'Crailsheim',
         'Cuxhaven', 'Dachau', 'Darmstadt', 'Deggendorf', 'Delitzsch', 'Demmin',
         'Dessau', 'Dieburg', 'Diepholz', 'Dinkelsbühl', 'Dinslaken',
@@ -72,19 +72,19 @@ class Provider(AddressProvider):
         'Mallersdorf', 'Marienberg', 'Marktheidenfeld', 'Mayen', 'Meiningen',
         'Meißen', 'Melle', 'Mellrichstadt', 'Melsungen', 'Meppen', 'Merseburg',
         'Mettmann', 'Miesbach', 'Miltenberg', 'Mittweida', 'Moers', 'Monschau',
-        'Mühldorfm Inn', 'Mühlhausen', 'München', 'Nabburg', 'Naila', 'Nauen',
+        'Mühldorf am Inn', 'Mühlhausen', 'München', 'Nabburg', 'Naila', 'Nauen',
         'Neu-Ulm', 'Neubrandenburg', 'Neunburg vorm Wald', 'Neuruppin',
-        'Neuss', 'Neustadtm Rübenberge', 'Neustadtner Waldnaab', 'Neustrelitz',
+        'Neuss', 'Neustadt am Rübenberge', 'Neustadtner Waldnaab', 'Neustrelitz',
         'Niesky', 'Norden', 'Nordhausen', 'Northeim', 'Nördlingen',
         'Nürtingen', 'Oberviechtach', 'Ochsenfurt', 'Olpe', 'Oranienburg',
-        'Oschatz', 'Osterburg', 'Osterodem Harz', 'Paderborn', 'Parchim',
+        'Oschatz', 'Osterburg', 'Osterode am Harz', 'Paderborn', 'Parchim',
         'Parsberg', 'Pasewalk', 'Passau', 'Pegnitz', 'Peine', 'Perleberg',
-        'Pfaffenhofenner Ilm', 'Pinneberg', 'Pirmasens', 'Plauen', 'Potsdam',
+        'Pfaffenhofen an der Ilm', 'Pinneberg', 'Pirmasens', 'Plauen', 'Potsdam',
         'Prenzlau', 'Pritzwalk', 'Pößneck', 'Quedlinburg', 'Querfurt',
         'Rastatt', 'Rathenow', 'Ravensburg', 'Recklinghausen', 'Regen',
         'Regensburg', 'Rehau', 'Reutlingen', 'Ribnitz-Damgarten', 'Riesa',
         'Rochlitz', 'Rockenhausen', 'Roding', 'Rosenheim', 'Rostock', 'Roth',
-        'Rothenburg oberauber', 'Rottweil', 'Rudolstadt', 'Saarbrücken',
+        'Rothenburg ob der Tauber', 'Rottweil', 'Rudolstadt', 'Saarbrücken',
         'Saarlouis', 'Sangerhausen', 'Sankt Goar', 'Sankt Goarshausen',
         'Saulgau', 'Scheinfeld', 'Schleiz', 'Schlüchtern', 'Schmölln',
         'Schongau', 'Schrobenhausen', 'Schwabmünchen', 'Schwandorf',
diff --git a/faker/providers/bank/th_TH/__init__.py b/faker/providers/bank/th_TH/__init__.py
new file mode 100644
index 00000000..e2776732
--- /dev/null
+++ b/faker/providers/bank/th_TH/__init__.py
@@ -0,0 +1,64 @@
+from .. import Provider as BankProvider
+
+
+class Provider(BankProvider):
+    """Implement bank provider for ``th_TH`` locale."""
+
+    bban_format = "#" * 10
+    country_code = "TH"
+    swift_bank_codes = (
+        "AIAC",
+        "ANZB",
+        "BKKB",
+        "BAAB",
+        "BOFA",
+        "AYUD",
+        "BKCH",
+        "BOTH",
+        "BNPA",
+        "UBOB",
+        "CITI",
+        "CRES",
+        "DEUT",
+        "EXTH",
+        "GSBA",
+        "BHOB",
+        "ICBK",
+        "TIBT",
+        "CHAS",
+        "KASI",
+        "KKPB",
+        "KRTH",
+        "LAHR",
+        "ICBC",
+        "MHCB",
+        "OCBC",
+        "DCBB",
+        "SICO",
+        "SMEB",
+        "SCBL",
+        "SMBC",
+        "THBK",
+        "HSBC",
+        "TMBK",
+        "UOVB",
+    )
+    swift_location_codes = (
+        "BK",
+        "B2",
+        "BB",
+        "BX",
+        "2X",
+    )
+    swift_branch_codes = (
+        "BKO",
+        "BNA",
+        "RYO",
+        "CHB",
+        "IBF",
+        "SEC",
+        "HDY",
+        "CHM",
+        "NAV",
+        "XXX",
+    )
diff --git a/faker/providers/date_time/th_TH/__init__.py b/faker/providers/date_time/th_TH/__init__.py
new file mode 100644
index 00000000..26df6d1c
--- /dev/null
+++ b/faker/providers/date_time/th_TH/__init__.py
@@ -0,0 +1,349 @@
+import warnings
+
+from datetime import datetime
+
+from .. import Provider as DateTimeProvider
+
+# thai_strftime() code adapted from
+# https://gist.github.com/bact/b8afe49cb1ae62913e6c1e899dcddbdb
+# (Same code base with PyThaiNLP 2.x)
+# Public Domain or CC0 1.0 Universal
+
+_TH_ABBR_WEEKDAYS = ["จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"]
+_TH_FULL_WEEKDAYS = [
+    "วันจันทร์",
+    "วันอังคาร",
+    "วันพุธ",
+    "วันพฤหัสบดี",
+    "วันศุกร์",
+    "วันเสาร์",
+    "วันอาทิตย์",
+]
+
+_TH_ABBR_MONTHS = [
+    "ม.ค.",
+    "ก.พ.",
+    "มี.ค.",
+    "เม.ย.",
+    "พ.ค.",
+    "มิ.ย.",
+    "ก.ค.",
+    "ส.ค.",
+    "ก.ย.",
+    "ต.ค.",
+    "พ.ย.",
+    "ธ.ค.",
+]
+_TH_FULL_MONTHS = [
+    "มกราคม",
+    "กุมภาพันธ์",
+    "มีนาคม",
+    "เมษายน",
+    "พฤษภาคม",
+    "มิถุนายน",
+    "กรกฎาคม",
+    "สิงหาคม",
+    "กันยายน",
+    "ตุลาคม",
+    "พฤศจิกายน",
+    "ธันวาคม",
+]
+
+_HA_TH_DIGITS = str.maketrans("0123456789", "๐๑๒๓๔๕๖๗๘๙")
+_BE_AD_DIFFERENCE = 543
+
+_NEED_L10N = "AaBbCcDFGgvXxYy+"  # flags that need localization
+_EXTENSIONS = "EO-_0^#"  # extension flags
+
+
+# Standard conversion support for thai_strftime()
+def _std_strftime(dt_obj: datetime, fmt_char: str) -> str:
+    """
+    Standard datetime.strftime() with normalization and exception handling.
+    """
+    str_ = ""
+    try:
+        str_ = dt_obj.strftime("%{}".format(fmt_char))
+        if str_ == "%{}".format(fmt_char):
+            # normalize outputs for unsupported directives
+            # in different platforms
+            # unsupported "%Q" in platform A may return "Q"
+            # unsupported "%Q" in platform A may return "%Q"
+            str_ = fmt_char
+    except ValueError as err:  # pragma: no cover
+        # Unsupported directives may raise ValueError on Windows,
+        # in that case just use the fmt_char
+        warnings.warn(
+            (
+                "String format directive unknown/not support: %{}"
+                "The system raises this ValueError: {}".format(fmt_char, err)
+            ),
+            UserWarning,
+        )
+        str_ = fmt_char
+    return str_
+
+
+# Thai conversion support for thai_strftime()
+def _thai_strftime(
+    dt_obj: datetime, fmt_char: str, buddhist_era: bool = True,
+) -> str:
+    """
+    Conversion support for thai_strftime().
+
+    The fmt_char should be in _NEED_L10N when call this function.
+    """
+    str_ = ""
+    year = dt_obj.year
+    if buddhist_era:
+        year = year + _BE_AD_DIFFERENCE
+
+    if fmt_char == "A":
+        # National representation of the full weekday name
+        str_ = _TH_FULL_WEEKDAYS[dt_obj.weekday()]
+    elif fmt_char == "a":
+        # National representation of the abbreviated weekday
+        str_ = _TH_ABBR_WEEKDAYS[dt_obj.weekday()]
+    elif fmt_char == "B":
+        # National representation of the full month name
+        str_ = _TH_FULL_MONTHS[dt_obj.month - 1]
+    elif fmt_char == "b":
+        # National representation of the abbreviated month name
+        str_ = _TH_ABBR_MONTHS[dt_obj.month - 1]
+    elif fmt_char == "C":
+        # Thai Buddhist century (AD+543)/100 + 1 as decimal number;
+        str_ = str(int(year / 100) + 1).zfill(2)
+    elif fmt_char == "c":
+        # Locale’s appropriate date and time representation
+        # Wed  6 Oct 01:40:00 1976
+        # พ   6 ต.ค. 01:40:00 2519  <-- left-aligned weekday, right-aligned day
+        str_ = "{:<2} {:>2} {} {} {}".format(
+            _TH_ABBR_WEEKDAYS[dt_obj.weekday()],
+            dt_obj.day,
+            _TH_ABBR_MONTHS[dt_obj.month - 1],
+            dt_obj.strftime("%H:%M:%S"),
+            str(year).zfill(4),
+        )
+    elif fmt_char == "D":
+        # Equivalent to ``%m/%d/%y''
+        str_ = "{}/{}".format(
+            dt_obj.strftime("%m/%d"), (str(year)[-2:]).zfill(2),
+        )
+    elif fmt_char == "F":
+        # Equivalent to ``%Y-%m-%d''
+        str_ = "{}-{}".format(str(year).zfill(4), dt_obj.strftime("%m-%d"))
+    elif fmt_char == "G":
+        # ISO 8601 year with century representing the year that contains
+        # the greater part of the ISO week (%V). Monday as the first day
+        # of the week.
+        year_G = int(dt_obj.strftime("%G"))
+        if buddhist_era:
+            year_G = year_G + _BE_AD_DIFFERENCE
+        str_ = str(year_G).zfill(4)
+    elif fmt_char == "g":
+        # Same year as in ``%G'',
+        # but as a decimal number without century (00-99).
+        year_G = int(dt_obj.strftime("%G"))
+        if buddhist_era:
+            year_G = year_G + _BE_AD_DIFFERENCE
+        str_ = (str(year_G)[-2:]).zfill(2)
+    elif fmt_char == "v":
+        # BSD extension, ' 6-Oct-1976'
+        str_ = "{:>2}-{}-{}".format(
+            dt_obj.day, _TH_ABBR_MONTHS[dt_obj.month - 1], str(year).zfill(4),
+        )
+    elif fmt_char == "X":
+        # Locale’s appropriate time representation.
+        str_ = dt_obj.strftime("%H:%M:%S")
+    elif fmt_char == "x":
+        # Locale’s appropriate date representation.
+        str_ = "{}/{}/{}".format(
+            str(dt_obj.day).zfill(2),
+            str(dt_obj.month).zfill(2),
+            str(year).zfill(4),
+        )
+    elif fmt_char == "Y":
+        # Year with century
+        str_ = (str(year)).zfill(4)
+    elif fmt_char == "y":
+        # Year without century
+        str_ = (str(year)[-2:]).zfill(2)
+    elif fmt_char == "+":
+        # National representation of the date and time
+        # (the format is similar to that produced by date(1))
+        # Wed  6 Oct 1976 01:40:00
+        str_ = "{:<2} {:>2} {} {} {}".format(
+            _TH_ABBR_WEEKDAYS[dt_obj.weekday()],
+            dt_obj.day,
+            _TH_ABBR_MONTHS[dt_obj.month - 1],
+            year,
+            dt_obj.strftime("%H:%M:%S"),
+        )
+
+    return str_
+
+
+def thai_strftime(
+    dt_obj: datetime,
+    fmt: str = "%-d %b %Y",
+    thai_digit: bool = False,
+    buddhist_era: bool = True,
+) -> str:
+    """
+    Convert :class:`datetime.datetime` into Thai date and time format.
+
+    The formatting directives are similar to :func:`datatime.strrftime`.
+
+    This function uses Thai names and Thai Buddhist Era for these directives:
+        * **%a** - abbreviated weekday name
+        (i.e. "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา")
+        * **%A** - full weekday name
+        (i.e. "วันจันทร์", "วันอังคาร", "วันเสาร์", "วันอาทิตย์")
+        * **%b** - abbreviated month name
+        (i.e. "ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ธ.ค.")
+        * **%B** - full month name
+        (i.e. "มกราคม", "กุมภาพันธ์", "พฤศจิกายน", "ธันวาคม",)
+        * **%y** - year without century (i.e. "56", "10")
+        * **%Y** - year with century (i.e. "2556", "2410")
+        * **%c** - date and time representation
+        (i.e. "พ   6 ต.ค. 01:40:00 2519")
+        * **%v** - short date representation
+        (i.e. " 6-ม.ค.-2562", "27-ก.พ.-2555")
+    """
+    thaidate_parts = []
+
+    i = 0
+    fmt_len = len(fmt)
+    while i < fmt_len:
+        str_ = ""
+        if fmt[i] == "%":
+            j = i + 1
+            if j < fmt_len:
+                fmt_char = fmt[j]
+                if fmt_char in _NEED_L10N:  # requires localization?
+                    str_ = _thai_strftime(dt_obj, fmt_char, buddhist_era)
+                elif fmt_char in _EXTENSIONS:
+                    fmt_char_ext = fmt_char
+                    k = j + 1
+                    if k < fmt_len:
+                        fmt_char = fmt[k]
+                        if fmt_char in _NEED_L10N:
+                            str_ = _thai_strftime(
+                                dt_obj, fmt_char, buddhist_era,
+                            )
+                        else:
+                            str_ = _std_strftime(dt_obj, fmt_char)
+
+                        if fmt_char_ext == "-":
+                            # GNU libc extension,
+                            # no padding
+                            if str_[0] and str_[0] in " 0":
+                                str_ = str_[1:]
+                        elif fmt_char_ext == "_":
+                            # GNU libc extension,
+                            # explicitly specify space (" ") for padding
+                            if str_[0] and str_[0] == "0":
+                                str_ = " " + str_[1:]
+                        elif fmt_char_ext == "0":
+                            # GNU libc extension,
+                            # explicitly specify zero ("0") for padding
+                            if str_[0] and str_[0] == " ":
+                                str_ = "0" + str_[1:]
+                        elif fmt_char_ext == "^":
+                            # GNU libc extension,
+                            # convert to upper case
+                            str_ = str_.upper()
+                        elif fmt_char_ext == "#":
+                            # GNU libc extension,
+                            # swap case - useful for %Z
+                            str_ = str_.swapcase()
+                        elif fmt_char_ext == "E":
+                            # POSIX extension,
+                            # uses the locale's alternative representation
+                            # Not implemented yet
+                            pass
+                        elif fmt_char_ext == "O":
+                            # POSIX extension,
+                            # uses the locale's alternative numeric symbols
+                            str_ = str_.translate(_HA_TH_DIGITS)
+                        i = i + 1  # consume char after format char
+                    else:
+                        # format char at string's end has no meaning
+                        str_ = fmt_char_ext
+                else:  # not in _NEED_L10N nor _EXTENSIONS
+                    # no known localization available, use Python's default
+                    str_ = _std_strftime(dt_obj, fmt_char)
+
+                i = i + 1  # consume char after "%"
+            else:
+                # % char at string's end has no meaning
+                str_ = "%"
+        else:
+            str_ = fmt[i]
+
+        thaidate_parts.append(str_)
+        i = i + 1
+
+    thaidate_text = "".join(thaidate_parts)
+
+    if thai_digit:
+        thaidate_text = thaidate_text.translate(_HA_TH_DIGITS)
+
+    return thaidate_text
+
+
+class Provider(DateTimeProvider):
+    def date(
+        self,
+        pattern: str = "%-d %b %Y",
+        end_datetime=None,
+        thai_digit: bool = False,
+        buddhist_era: bool = True,
+    ):
+        """
+        Get a date string between January 1, 1970 and now
+        :param pattern format
+        :param end_datetime datetime
+        :param thai_digit use Thai digit or not (default: False)
+        :param buddhist_era use Buddist era or not (default: True)
+        :example '08 พ.ย. 2563'
+        :example '๐๘ พ.ย. 2563' (thai_digit = True)
+        :example '8 พฤศิจกายน 2020' (pattern = "%-d %B %Y", buddhist_era = False)
+        """
+        return thai_strftime(
+            self.date_time(end_datetime=end_datetime),
+            pattern,
+            thai_digit,
+            buddhist_era,
+        )
+
+    def time(
+        self, pattern="%H:%M:%S", end_datetime=None, thai_digit: bool = False,
+    ):
+        """
+        Get a time string (24h format by default)
+        :param pattern format
+        :param end_datetime datetime
+        :param thai_digit use Thai digit or not (default: False)
+        :example '15:02:34'
+        :example '๑๕:๐๒:๓๔' (thai_digit = True)
+        """
+        return thai_strftime(
+            self.date_time(end_datetime=end_datetime).time(),
+            pattern,
+            thai_digit,
+        )
+
+    def century(self, thai_digit: bool = False, buddhist_era: bool = True):
+        """
+        :param thai_digit use Thai digit or not (default: False)
+        :param buddhist_era use Buddist era or not (default: True)
+        :example '20'
+        """
+        end_century = 22
+        if buddhist_era:
+            end_century = 26
+        text = str(self.random_element(range(1, end_century)))
+        if thai_digit:
+            text = text.translate(_HA_TH_DIGITS)
+        return text
diff --git a/faker/providers/person/hu_HU/__init__.py b/faker/providers/person/hu_HU/__init__.py
index 5ac8fe24..295fea62 100644
--- a/faker/providers/person/hu_HU/__init__.py
+++ b/faker/providers/person/hu_HU/__init__.py
@@ -35,7 +35,8 @@ class Provider(PersonProvider):
         ('{{prefix}} {{last_name}} {{last_name}} {{first_name_male}}', 0.05),
         ('{{prefix}} {{last_name}} {{first_name_male}} {{first_name_male}}', 0.05),
         ('{{prefix}} {{first_name_male_abbreviated}} {{last_name}} {{first_name_male}}', 0.05),
-        ('{{prefix}} {{last_name}} {{first_name_male_abbreviated}} {{first_name_male}}', 0.05)))
+        ('{{prefix}} {{last_name}} {{first_name_male_abbreviated}} {{first_name_male}}', 0.05),
+    ))
 
     formats_female = OrderedDict((
         ('{{last_name}} {{first_name_female}}', 0.1),
@@ -103,118 +104,118 @@ class Provider(PersonProvider):
     ))
 
     first_names_male = OrderedDict((
-        ("László", 0.06640477), ("István", 0.060906051), ("József",
-                                                          0.054476881), ("János", 0.047506017),
-        ("Zoltán", 0.045579697), ("Sándor", 0.037170944), ("Gábor",
-                                                           0.035546303), ("Ferenc", 0.034065759),
-        ("Attila", 0.032146512), ("Péter", 0.03083703), ("Tamás",
-                                                         0.030257321), ("Zsolt", 0.025204158),
-        ("Tibor", 0.023296182), ("András", 0.021678391), ("Csaba",
-                                                          0.020367141), ("Imre", 0.019339667),
-        ("Lajos", 0.017901558), ("György", 0.01695188), ("Balázs",
-                                                         0.015569685), ("Gyula", 0.014295123),
-        ("Mihály", 0.013628337), ("Róbert", 0.013385668), ("Károly",
-                                                           0.013181456), ("Dávid", 0.01315184),
-        ("Dániel", 0.012373665), ("Ádám", 0.012290124), ("Béla",
-                                                         0.012279294), ("Krisztián", 0.011589081),
-        ("Miklós", 0.010985283), ("Norbert", 0.010746593), ("Bence",
-                                                            0.010403586), ("Máté", 0.009479986),
-        ("Pál", 0.007890264), ("Gergő", 0.007554993), ("Roland",
-                                                       0.007535765), ("Szabolcs", 0.007522062),
-        ("Bálint", 0.007021254), ("Levente", 0.006948763), ("Márk",
-                                                            0.006873178), ("Richárd", 0.006811074),
-        ("Antal", 0.006583213), ("Gergely", 0.006408174), ("Ákos",
-                                                           0.006278662), ("Viktor", 0.005872447),
-        ("Árpád", 0.005217153), ("Márton", 0.005061783), ("Géza",
-                                                          0.005036367), ("Kristóf", 0.004518984),
-        ("Milán", 0.003956735), ("Dominik", 0.003924247), ("Patrik",
-                                                           0.003911428), ("Martin", 0.003747439),
-        ("Barnabás", 0.003645333), ("Jenő", 0.003619917), ("Kálmán",
-                                                           0.003613728), ("Marcell", 0.003571515),
-        ("Áron", 0.003219668), ("Mátyás", 0.003028495), ("Ernő",
-                                                         0.002998879), ("Endre", 0.002830912),
-        ("Botond", 0.00282605), ("Zsombor", 0.002768366), ("Dezső",
-                                                           0.002557523), ("Olivér", 0.002524814),
-        ("Nándor", 0.002520394), ("Szilárd",
-                                  0.002422044), ("Erik", 0.002421381), ("Alex", 0.0023248),
-        ("Benedek", 0.002119924), ("Vilmos", 0.002113515), ("Kornél",
-                                                            0.002018481), ("Zalán", 0.001970964),
-        ("Dénes", 0.001921458), ("Ottó", 0.001901788), ("Benjámin",
-                                                        0.001738241), ("Bertalan", 0.001700227),
-        ("Kevin", 0.001668623), ("Adrián", 0.001550603), ("Rudolf",
-                                                          0.001386172), ("Noel", 0.001381973),
-        ("Albert", 0.001355673), ("Vince", 0.001353463), ("Ervin",
-                                                          0.001182622), ("Győző", 0.001125823),
-        ("Zsigmond", 0.001120519), ("Andor", 0.001057531), ("Iván",
-                                                            0.001016202), ("Szilveszter", 0.001010014),
-        ("Gusztáv", 0.000994985), ("Barna", 0.000986808), ("Ábel",
-                                                           0.000969569), ("Hunor", 0.000940396),
-        ("Arnold", 0.000931777), ("Csongor", 0.00092824), ("Elemér",
-                                                           0.000894868), ("Krisztofer", 0.000891111),
-        ("Bendegúz", 0.000868347), ("Emil", 0.000791656), ("Tivadar", 0.000786573), ("Henrik", 0.000758063)))
+        ("László", 0.06640477), ("István", 0.060906051),
+        ("József", 0.054476881), ("János", 0.047506017),
+        ("Zoltán", 0.045579697), ("Sándor", 0.037170944),
+        ("Gábor", 0.035546303), ("Ferenc", 0.034065759),
+        ("Attila", 0.032146512), ("Péter", 0.03083703),
+        ("Tamás", 0.030257321), ("Zsolt", 0.025204158),
+        ("Tibor", 0.023296182), ("András", 0.021678391),
+        ("Csaba", 0.020367141), ("Imre", 0.019339667),
+        ("Lajos", 0.017901558), ("György", 0.01695188),
+        ("Balázs", 0.015569685), ("Gyula", 0.014295123),
+        ("Mihály", 0.013628337), ("Róbert", 0.013385668),
+        ("Károly", 0.013181456), ("Dávid", 0.01315184),
+        ("Dániel", 0.012373665), ("Ádám", 0.012290124),
+        ("Béla", 0.012279294), ("Krisztián", 0.011589081),
+        ("Miklós", 0.010985283), ("Norbert", 0.010746593),
+        ("Bence", 0.010403586), ("Máté", 0.009479986),
+        ("Pál", 0.007890264), ("Gergő", 0.007554993),
+        ("Roland", 0.007535765), ("Szabolcs", 0.007522062),
+        ("Bálint", 0.007021254), ("Levente", 0.006948763),
+        ("Márk", 0.006873178), ("Richárd", 0.006811074),
+        ("Antal", 0.006583213), ("Gergely", 0.006408174),
+        ("Ákos", 0.006278662), ("Viktor", 0.005872447),
+        ("Árpád", 0.005217153), ("Márton", 0.005061783),
+        ("Géza", 0.005036367), ("Kristóf", 0.004518984),
+        ("Milán", 0.003956735), ("Dominik", 0.003924247),
+        ("Patrik", 0.003911428), ("Martin", 0.003747439),
+        ("Barnabás", 0.003645333), ("Jenő", 0.003619917),
+        ("Kálmán", 0.003613728), ("Marcell", 0.003571515),
+        ("Áron", 0.003219668), ("Mátyás", 0.003028495),
+        ("Ernő",  0.002998879), ("Endre", 0.002830912),
+        ("Botond", 0.00282605), ("Zsombor", 0.002768366),
+        ("Dezső", 0.002557523), ("Olivér", 0.002524814),
+        ("Nándor", 0.002520394), ("Szilárd", 0.002422044),
+        ("Erik", 0.002421381), ("Alex", 0.0023248),
+        ("Benedek", 0.002119924), ("Vilmos", 0.002113515),
+        ("Kornél",  0.002018481), ("Zalán", 0.001970964),
+        ("Dénes", 0.001921458), ("Ottó", 0.001901788),
+        ("Benjámin", 0.001738241), ("Bertalan", 0.001700227),
+        ("Kevin", 0.001668623), ("Adrián", 0.001550603),
+        ("Rudolf", 0.001386172), ("Noel", 0.001381973),
+        ("Albert", 0.001355673), ("Vince", 0.001353463),
+        ("Ervin", 0.001182622), ("Győző", 0.001125823),
+        ("Zsigmond", 0.001120519), ("Andor", 0.001057531),
+        ("Iván", 0.001016202), ("Szilveszter", 0.001010014),
+        ("Gusztáv", 0.000994985), ("Barna", 0.000986808),
+        ("Ábel", 0.000969569), ("Hunor", 0.000940396),
+        ("Arnold", 0.000931777), ("Csongor", 0.00092824),
+        ("Elemér", 0.000894868), ("Krisztofer", 0.000891111),
+        ("Bendegúz", 0.000868347), ("Emil", 0.000791656),
+        ("Tivadar", 0.000786573), ("Henrik", 0.000758063),
+    ))
 
     first_names_female = OrderedDict((
-        ("Mária", 0.076200074), ("Erzsébet",
-                                 0.058002384), ("Katalin", 0.0429636), ("Éva", 0.039004017),
-        ("Ilona", 0.038027669), ("Anna", 0.030819538), ("Zsuzsanna",
-                                                        0.029737292), ("Margit", 0.024148354),
-        ("Judit", 0.020956031), ("Ágnes", 0.020891678), ("Andrea",
-                                                         0.020768845), ("Ildikó", 0.019861817),
-        ("Julianna", 0.019458091), ("Erika", 0.018991368), ("Krisztina",
-                                                            0.017491847), ("Irén", 0.015454477),
-        ("Eszter", 0.014382165), ("Mónika", 0.014128821), ("Magdolna",
-                                                           0.013536554), ("Edit", 0.013129441),
-        ("Gabriella", 0.012887838), ("Szilvia", 0.012663621), ("Anita",
-                                                               0.011554053), ("Viktória", 0.011388318),
-        ("Anikó", 0.011180584), ("Márta", 0.010886596), ("Tímea",
-                                                         0.010327747), ("Rozália", 0.009782898),
-        ("Piroska", 0.009699353), ("Ibolya", 0.00922134), ("Klára",
-                                                           0.008981769), ("Tünde", 0.008838839),
-        ("Dóra", 0.008803841), ("Zsófia", 0.008600397), ("Alexandra",
-                                                         0.007886652), ("Veronika", 0.00777443),
-        ("Gizella", 0.007579567), ("Csilla", 0.007395768), ("Nikolett",
-                                                            0.006972849), ("Melinda", 0.006857693),
-        ("Réka", 0.0068385), ("Nóra", 0.006794469), ("Terézia",
-                                                     0.006777535), ("Adrienn", 0.006753826),
-        ("Beáta", 0.006526674), ("Marianna", 0.006462547), ("Vivien",
-                                                            0.006299747), ("Renáta", 0.00626091),
-        ("Barbara", 0.006076434), ("Enikő", 0.006052499), ("Bernadett",
-                                                           0.005964438), ("Rita", 0.005917472),
-        ("Brigitta", 0.005875926), ("Edina", 0.005745866), ("Hajnalka",
-                                                            0.005696191), ("Gyöngyi", 0.005616484),
-        ("Petra", 0.005609033), ("Boglárka", 0.005329496), ("Orsolya",
-                                                            0.005328141), ("Jolán", 0.005184534),
-        ("Noémi", 0.005078861), ("Etelka", 0.004833419), ("Valéria",
-                                                          0.00472594), ("Fanni", 0.004716682),
-        ("Borbála", 0.004701553), ("Annamária",
-                                   0.004528367), ("Kitti", 0.00439334), ("Teréz", 0.004384985),
-        ("Nikoletta", 0.004310021), ("Laura", 0.004266893), ("Emese",
-                                                             0.004212702), ("Lilla", 0.004193961),
-        ("Hanna", 0.003921198), ("Aranka", 0.003884844), ("Kinga",
-                                                          0.003755914), ("Klaudia", 0.003710077),
-        ("Anett", 0.003661305), ("Róza", 0.003621339), ("Lili",
-                                                        0.003436636), ("Zita", 0.00343212),
-        ("Dorina", 0.003412476), ("Emma", 0.003374994), ("Beatrix",
-                                                         0.003364381), ("Zsanett", 0.003276772),
-        ("Sára", 0.003156873), ("Bianka", 0.003061135), ("Rózsa",
-                                                         0.003006041), ("Jázmin", 0.002952527),
-        ("Luca", 0.002949817), ("Júlia", 0.002917754), ("Diána",
-                                                        0.002841434), ("Henrietta", 0.002798759),
-        ("Györgyi", 0.002731471), ("Irma", 0.00272131), ("Dorottya",
-                                                         0.002585154), ("Bettina", 0.002574316),
-        ("Mariann", 0.002569349), ("Virág", 0.002557156), ("Gréta", 0.002515835), ("Rebeka", 0.002513351)))
+        ("Mária", 0.076200074), ("Erzsébet", 0.058002384),
+        ("Katalin", 0.0429636), ("Éva", 0.039004017),
+        ("Ilona", 0.038027669), ("Anna", 0.030819538),
+        ("Zsuzsanna", 0.029737292), ("Margit", 0.024148354),
+        ("Judit", 0.020956031), ("Ágnes", 0.020891678),
+        ("Andrea", 0.020768845), ("Ildikó", 0.019861817),
+        ("Julianna", 0.019458091), ("Erika", 0.018991368),
+        ("Krisztina", 0.017491847), ("Irén", 0.015454477),
+        ("Eszter", 0.014382165), ("Mónika", 0.014128821),
+        ("Magdolna", 0.013536554), ("Edit", 0.013129441),
+        ("Gabriella", 0.012887838), ("Szilvia", 0.012663621),
+        ("Anita", 0.011554053), ("Viktória", 0.011388318),
+        ("Anikó", 0.011180584), ("Márta", 0.010886596),
+        ("Tímea", 0.010327747), ("Rozália", 0.009782898),
+        ("Piroska", 0.009699353), ("Ibolya", 0.00922134),
+        ("Klára", 0.008981769), ("Tünde", 0.008838839),
+        ("Dóra", 0.008803841), ("Zsófia", 0.008600397),
+        ("Alexandra", 0.007886652), ("Veronika", 0.00777443),
+        ("Gizella", 0.007579567), ("Csilla", 0.007395768),
+        ("Nikolett", 0.006972849), ("Melinda", 0.006857693),
+        ("Réka", 0.0068385), ("Nóra", 0.006794469),
+        ("Terézia", 0.006777535), ("Adrienn", 0.006753826),
+        ("Beáta", 0.006526674), ("Marianna", 0.006462547),
+        ("Vivien", 0.006299747), ("Renáta", 0.00626091),
+        ("Barbara", 0.006076434), ("Enikő", 0.006052499),
+        ("Bernadett", 0.005964438), ("Rita", 0.005917472),
+        ("Brigitta", 0.005875926), ("Edina", 0.005745866),
+        ("Hajnalka", 0.005696191), ("Gyöngyi", 0.005616484),
+        ("Petra", 0.005609033), ("Boglárka", 0.005329496),
+        ("Orsolya", 0.005328141), ("Jolán", 0.005184534),
+        ("Noémi", 0.005078861), ("Etelka", 0.004833419),
+        ("Valéria", 0.00472594), ("Fanni", 0.004716682),
+        ("Borbála", 0.004701553), ("Annamária", 0.004528367),
+        ("Kitti", 0.00439334), ("Teréz", 0.004384985),
+        ("Nikoletta", 0.004310021), ("Laura", 0.004266893),
+        ("Emese", 0.004212702), ("Lilla", 0.004193961),
+        ("Hanna", 0.003921198), ("Aranka", 0.003884844),
+        ("Kinga", 0.003755914), ("Klaudia", 0.003710077),
+        ("Anett", 0.003661305), ("Róza", 0.003621339),
+        ("Lili", 0.003436636), ("Zita", 0.00343212),
+        ("Dorina", 0.003412476), ("Emma", 0.003374994),
+        ("Beatrix", 0.003364381), ("Zsanett", 0.003276772),
+        ("Sára", 0.003156873), ("Bianka", 0.003061135),
+        ("Rózsa",  0.003006041), ("Jázmin", 0.002952527),
+        ("Luca", 0.002949817), ("Júlia", 0.002917754),
+        ("Diána", 0.002841434), ("Henrietta", 0.002798759),
+        ("Györgyi", 0.002731471), ("Irma", 0.00272131),
+        ("Dorottya", 0.002585154), ("Bettina", 0.002574316),
+        ("Mariann", 0.002569349), ("Virág", 0.002557156),
+        ("Gréta", 0.002515835), ("Rebeka", 0.002513351),
+    ))
 
     first_names = first_names_male.copy()
     first_names.update(first_names_female)
 
-    prefixes = OrderedDict((('Dr.', 0.95), ('Prof. Dr.', 0.05)))
+    prefixes = OrderedDict((("Dr.", 0.95), ("Prof. Dr.", 0.05)))
 
     def first_name_male_abbreviated(self):
-        if hasattr(self, 'first_names_male'):
-            return self.random_element(self.first_names_male)[0] + "."
-        return self.first_name()[0]
+        return self.random_element(self.first_names_male)[0] + "."
 
     def first_name_female_abbreviated(self):
-        if hasattr(self, 'first_names_female'):
-            return self.random_element(self.first_names_female)[0] + "."
-        return self.first_name()[0]
+        return self.random_element(self.first_names_female)[0] + "."
diff --git a/faker/providers/person/ja_JP/__init__.py b/faker/providers/person/ja_JP/__init__.py
index 28cd36ab..4db952fe 100644
--- a/faker/providers/person/ja_JP/__init__.py
+++ b/faker/providers/person/ja_JP/__init__.py
@@ -1,225 +1,309 @@
 from collections import OrderedDict
+from operator import itemgetter
 
 from .. import Provider as PersonProvider
 
 
 class Provider(PersonProvider):
-    formats_female = (
-        '{{last_name}} {{first_name_female}}',
-    )
-
-    formats_male = (
-        '{{last_name}} {{first_name_male}}',
-    )
-
-    formats = formats_male + formats_female
-
     # link: http://dic.nicovideo.jp/a/日本人の名前一覧
     # link: http://www.meijiyasuda.co.jp/enjoy/ranking/
-    first_names_female = (
-        '明美', 'あすか', '香織', '加奈', 'くみ子', 'さゆり', '知実', '千代',
-        '直子', '七夏', '花子', '春香', '真綾', '舞', '美加子', '幹',
-        '桃子', '結衣', '裕美子', '陽子', '里佳',
+    first_name_female_pairs = (
+        ('明美', 'アケミ', 'Akemi'),
+        ('あすか', 'アスカ', 'Asuka'),
+        ('香織', 'カオリ', 'Kaori'),
+        ('加奈', 'カナ', 'Kana'),
+        ('くみ子', 'クミコ', 'Kumiko'),
+        ('さゆり', 'サユリ', 'Sayuri'),
+        ('知実', 'サトミ', 'Satomi'),
+        ('千代', 'チヨ', 'Chiyo'),
+        ('直子', 'ナオコ', 'Naoko'),
+        ('七夏', 'ナナミ', 'Nanami'),
+        ('花子', 'ハナコ', 'Hanako'),
+        ('春香', 'ハルカ', 'Haruka'),
+        ('真綾', 'マアヤ', 'Maaya'),
+        ('舞', 'マイ', 'Mai'),
+        ('美加子', 'ミカコ', 'Mikako'),
+        ('幹', 'ミキ', 'Miki'),
+        ('桃子', 'モモコ', 'Momoko'),
+        ('結衣', 'ユイ', 'Yui'),
+        ('裕美子', 'ユミコ', 'Yumiko'),
+        ('陽子', 'ヨウコ', 'Yoko'),
+        ('里佳', 'リカ', 'Rika'),
     )
 
-    # link: http://dic.nicovideo.jp/a/日本人の名前一覧
-    # link: http://www.meijiyasuda.co.jp/enjoy/ranking/
-    first_names_male = (
-        '晃', '篤司', '治', '和也', '京助', '健一', '修平', '翔太',
-        '淳', '聡太郎', '太一', '太郎', '拓真', '翼', '智也', '直樹',
-        '直人', '英樹', '浩', '学', '充', '稔', '裕樹', '裕太',
-        '康弘', '陽一', '洋介', '亮介', '涼平', '零',
+    # for backwards compatibility
+    first_names_female = tuple(map(itemgetter(0), first_name_female_pairs))
+    first_kana_names_female = tuple(map(itemgetter(1), first_name_female_pairs))
+    first_romanized_names_female = tuple(map(itemgetter(2), first_name_female_pairs))
+
+    first_name_male_pairs = (
+        ('晃', 'アキラ', 'Akira'),
+        ('篤司', 'アツシ', 'Atsushi'),
+        ('治', 'オサム', 'Osamu'),
+        ('和也', 'カズヤ', 'Kazuya'),
+        ('京助', 'キョウスケ', 'Kyosuke'),
+        ('健一', 'ケンイチ', 'Kenichi'),
+        ('修平', 'シュウヘイ', 'Shohei'),
+        ('翔太', 'ショウタ', 'Shota'),
+        ('淳', 'ジュン', 'Jun'),
+        ('聡太郎', 'ソウタロウ', 'Sotaro'),
+        ('太一', 'タイチ', 'Taichi'),
+        ('太郎', 'タロウ', 'Taro'),
+        ('拓真', 'タクマ', 'Takuma'),
+        ('翼', 'ツバサ', 'Tsubasa'),
+        ('智也', 'トモヤ', 'Tomoya'),
+        ('直樹', 'ナオキ', 'Naoki'),
+        ('直人', 'ナオト', 'Naoto'),
+        ('英樹', 'ヒデキ', 'Hideki'),
+        ('浩', 'ヒロシ', 'Hiroshi'),
+        ('学', 'マナブ', 'Manabu'),
+        ('充', 'ミツル', 'Mituru'),
+        ('稔', 'ミノル', 'Minoru'),
+        ('裕樹', 'ユウキ', 'Yuki'),
+        ('裕太', 'ユウタ', 'Yuta'),
+        ('康弘', 'ヤスヒロ', 'Yasuhiro'),
+        ('陽一', 'ヨウイチ', 'Yoichi'),
+        ('洋介', 'ヨウスケ', 'Yosuke'),
+        ('亮介', 'リョウスケ', 'Ryosuke'),
+        ('涼平', 'リョウヘイ', 'Ryohei'),
+        ('零', 'レイ', 'Rei'),
     )
 
+    # for backwards compatibility
+    first_names_male = tuple(map(itemgetter(0), first_name_male_pairs))
+    first_kana_names_male = tuple(map(itemgetter(1), first_name_male_pairs))
+    first_romanized_names_male = tuple(map(itemgetter(2), first_name_male_pairs))
+
+    # for backwards compatibility
     first_names = first_names_male + first_names_female
+    first_kana_names = first_kana_names_male + first_kana_names_female
+    first_romanized_names = first_romanized_names_male \
+        + first_romanized_names_female
 
-    # based on: https://www2.nipponsoft.co.jp/bldoko/index.asp
-    last_names = OrderedDict((
-        ("佐藤", 366803),
-        ("鈴木", 321135),
-        ("高橋", 266782),
-        ("田中", 245821),
-        ("伊藤", 203357),
-        ("渡辺", 200504),
-        ("山本", 200134),
-        ("中村", 195219),
-        ("小林", 191819),
-        ("加藤", 160283),
-        ("吉田", 154461),
-        ("山田", 151675),
-        ("佐々木", 135927),
-        ("山口", 119501),
-        ("松本", 116490),
-        ("井上", 111287),
-        ("木村", 107446),
-        ("林", 101826),
-        ("斎藤", 101774),
-        ("清水", 97826),
-        ("山崎", 90781),
-        ("阿部", 86833),
-        ("森", 86507),
-        ("池田", 84860),
-        ("橋本", 82836),
-        ("山下", 80588),
-        ("石川", 77471),
-        ("中島", 74106),
-        ("前田", 72930),
-        ("藤田", 72375),
-        ("後藤", 71629),
-        ("小川", 71179),
-        ("岡田", 70347),
-        ("長谷川", 69201),
-        ("村上", 68606),
-        ("近藤", 68297),
-        ("石井", 67079),
-        ("遠藤", 62620),
-        ("斉藤", 62540),
-        ("坂本", 62308),
-        ("青木", 59516),
-        ("藤井", 59204),
-        ("西村", 58821),
-        ("福田", 58714),
-        ("太田", 58439),
-        ("三浦", 58006),
-        ("藤原", 57742),
-        ("松田", 55883),
-        ("岡本", 55539),
-        ("中川", 55221),
+    first_name_pairs = first_name_male_pairs + first_name_female_pairs
+
+    last_name_pairs = OrderedDict((
+        (("佐藤", "サトウ", "Sato"), 366803),
+        (("鈴木", "スズキ", "Suzuki"), 321135),
+        (("高橋", "タカハシ", "Takahashi"), 266782),
+        (("田中", "タナカ", "Tanaka"), 245821),
+        (("伊藤", "イトウ", "Ito"), 203357),
+        (("渡辺", "ワタナベ", "Watanabe"), 200504),
+        (("山本", "ヤマモト", "Yamamoto"), 200134),
+        (("中村", "ナカムラ", "Nakamura"), 195219),
+        (("小林", "コバヤシ", "Kobayashi"), 191819),
+        (("加藤", "カトウ", "Kato"), 160283),
+        (("吉田", "ヨシダ", "Yoshida"), 154461),
+        (("山田", "ヤマダ", "Yamada"), 151675),
+        (("佐々木", "ササキ", "Sasaki"), 135927),
+        (("山口", "ヤマグチ", "Yamaguchi"), 119501),
+        (("松本", "マツモト", "Matsumoto"), 116490),
+        (("井上", "イノウエ", "Inoue"), 111287),
+        (("木村", "キムラ", "Kimura"), 107446),
+        (("林", "ハヤシ", "Hayashi"), 101826),
+        (("斎藤", "サイトウ", "Saito"), 101774),
+        (("清水", "シミズ", "Shimizu"), 97826),
+        (("山崎", "ヤマザキ", "Yamazaki"), 90781),
+        (("阿部", "アベ", "Abe"), 86833),
+        (("森", "モリ", "Mori"), 86507),
+        (("池田", "イケダ", "Ikeda"), 84860),
+        (("橋本", "ハシモト", "Hashimoto"), 82836),
+        (("山下", "ヤマシタ", "Yamashita"), 80588),
+        (("石川", "イシカワ", "Ishikawa"), 77471),
+        (("中島", "ナカジマ", "Nakajima"), 74106),
+        (("前田", "マエダ", "Maeda"), 72930),
+        (("藤田", "フジタ", "Fujita"), 72375),
+        (("後藤", "ゴトウ", "Goto"), 71629),
+        (("小川", "オガワ", "Ogawa"), 71179),
+        (("岡田", "オカダ", "Okada"), 70347),
+        (("長谷川", "ハセガワ", "Hasegawa"), 69201),
+        (("村上", "ムラカミ", "Murakami"), 68606),
+        (("近藤", "コンドウ", "Kondo"), 68297),
+        (("石井", "イシイ", "Ishii"), 67079),
+        (("遠藤", "エンドウ", "Endo"), 62620),
+        (("斉藤", "サイトウ", "Saito"), 62540),
+        (("坂本", "サカモト", "Sakamoto"), 62308),
+        (("青木", "アオキ", "Aoki"), 59516),
+        (("藤井", "フジイ", "Fujii"), 59204),
+        (("西村", "ニシムラ", "Nishimura"), 58821),
+        (("福田", "フクダ", "Fukuda"), 58714),
+        (("太田", "オオタ", "Ota"), 58439),
+        (("三浦", "ミウラ", "Miura"), 58006),
+        (("藤原", "フジワラ", "Fujiwara"), 57742),
+        (("松田", "マツダ", "Matsuda"), 55883),
+        (("岡本", "オカモト", "Okamoto"), 55539),
+        (("中川", "ナカガワ", "Nakagawa"), 55221),
     ))
 
-    kana_formats = (
-        '{{last_kana_name}} {{first_kana_name_female}}',
-        '{{last_kana_name}} {{first_kana_name_male}}',
-    )
+    # for backwards compatibility only. use the pairs instead
+    last_names = tuple(map(itemgetter(0), last_name_pairs))
+    last_kana_names = tuple(map(itemgetter(1), last_name_pairs))
+    last_romanized_names = tuple(map(itemgetter(2), last_name_pairs))
 
-    first_kana_names_female = (
-        'アケミ', 'アスカ', 'カオリ', 'カナ',
-        'クミコ', 'サユリ', 'サトミ', 'チヨ',
-        'ナオコ', 'ナナミ', 'ハナコ', 'ハルカ',
-        'マアヤ', 'マイ', 'ミカコ', 'ミキ',
-        'モモコ', 'ユイ', 'ユミコ', 'ヨウコ',
-        'リカ',
+    formats_male = (
+        '{{last_name}} {{first_name_male}}',
     )
 
-    first_kana_names_male = (
-        'アキラ', 'アツシ', 'オサム', 'カズヤ',
-        'キョウスケ', 'ケンイチ', 'シュウヘイ', 'ショウタ',
-        'ジュン', 'ソウタロウ', 'タイチ', 'タロウ',
-        'タクマ', 'ツバサ', 'トモヤ', 'ナオキ',
-        'ナオト', 'ヒデキ', 'ヒロシ', 'マナブ',
-        'ミツル', 'ミノル', 'ユウキ', 'ユウタ',
-        'ヤスヒロ', 'ヨウイチ', 'ヨウスケ', 'リョウスケ',
-        'リョウヘイ', 'レイ',
+    formats_female = (
+        '{{last_name}} {{first_name_female}}',
     )
 
-    first_kana_names = first_kana_names_male + first_kana_names_female
+    formats = formats_male + formats_female
 
-    last_kana_names = (
-        'アオタ', 'アオヤマ', 'イシダ', 'イダカ',
-        'イトウ', 'イノウエ', 'ウノ', 'エコダ',
-        'オオガキ', 'カトウ', 'カノウ', 'キジマ',
-        'キムラ', 'キリヤマ', 'クドウ', 'コイズミ',
-        'コバヤシ', 'コンドウ', 'サイトウ', 'サカモト',
-        'ササキ', 'サトウ', 'ササダ', 'スズキ',
-        'スギヤマ', 'タカハシ', 'タナカ', 'タナベ',
-        'ツダ', 'ナカジマ', 'ナカムラ', 'ナギサ',
-        'ナカツガワ', 'ニシノソノ', 'ノムラ', 'ハラダ',
-        'ハマダ', 'ヒロカワ', 'フジモト', 'マツモト',
-        'ミヤケ', 'ミヤザワ', 'ムラヤマ', 'ヤマギシ',
-        'ヤマグチ', 'ヤマダ', 'ヤマモト', 'ヨシダ',
-        'ヨシモト', 'ワカマツ', 'ワタナベ',
+    kana_formats_male = (
+        '{{last_kana_name}} {{first_kana_name_male}}',
     )
 
-    romanized_formats = (
-        '{{first_romanized_name_female}} {{last_romanized_name}}',
-        '{{first_romanized_name_male}} {{last_romanized_name}}',
+    kana_formats_female = (
+        '{{last_kana_name}} {{first_kana_name_female}}',
     )
 
-    first_romanized_names_female = (
-        'Akemi', 'Asuka', 'Kaori', 'Kana',
-        'Kumiko', 'Sayuri', 'Satomi', 'Chiyo',
-        'Naoko', 'Nanami', 'Hanako', 'Haruka',
-        'Maaya', 'Mai', 'Mikako', 'Miki',
-        'Momoko', 'Yui', 'Yumiko', 'Yoko',
-        'Rika',
+    kana_formats = kana_formats_male + kana_formats_female
+
+    romanized_formats_male = (
+        '{{first_romanized_name_male}} {{last_romanized_name}}',
     )
 
-    first_romanized_names_male = (
-        'Akira', 'Atsushi', 'Osamu', 'Kazuya',
-        'Kyosuke', 'Kenichi', 'Shohei', 'Shota',
-        'Jun', 'Sotaro', 'Taichi', 'Taro',
-        'Takuma', 'Tsubasa', 'Tomoya', 'Naoki',
-        'Naoto', 'Hideki', 'Hiroshi', 'Manabu',
-        'Mituru', 'Minoru', 'Yuki', 'Yuta',
-        'Yasuhiro', 'Yoichi', 'Yosuke', 'Ryosuke',
-        'Ryohei', 'Rei',
+    romanized_formats_female = (
+        '{{first_romanized_name_female}} {{last_romanized_name}}',
     )
 
-    first_romanized_names = first_romanized_names_male \
-        + first_romanized_names_female
+    romanized_formats = romanized_formats_male + romanized_formats_female
 
-    last_romanized_names = (
-        'Aota', 'Aoyama', 'Ishida', 'Idaka',
-        'Ito', 'Inoue', 'Uno', 'Ekoda',
-        'Ogaki', 'Kato', 'Kano', 'Kijima',
-        'Kimura', 'Kiriyama', 'Kudo', 'Koizumi',
-        'Kobayashi', 'Kondo', 'Saito', 'Sakamoto',
-        'Sasaki', 'Sato', 'Sasada', 'Suzuki',
-        'Sugiyama', 'Takahashi', 'Tanaka', 'Tanabe',
-        'Tsuda', 'Nakajima', 'Nakamura', 'Nagisa',
-        'Nakatsugawa', 'Nishinosono', 'Nomura', 'Harada',
-        'Hamada', 'Hirokawa', 'Fujimoto', 'Matsumoto',
-        'Miyake', 'Miyagawa', 'Murayama', 'Yamagishi',
-        'Yamaguchi', 'Yamada', 'Yamamoto', 'Yoshida',
-        'Yoshimoto', 'Wakamatsu', 'Watanabe',
-    )
+    def first_name_pair(self):
+        """
+        @example ('明美', 'アケミ', 'Akemi')
+        """
+        return self.random_element(self.first_name_pairs)
 
-    def kana_name(self):
-        '''
-        @example 'アオタ アキラ'
-        '''
-        pattern = self.random_element(self.kana_formats)
-        return self.generator.parse(pattern)
+    def first_name_male_pair(self):
+        """
+        @example ('晃', 'アキラ', 'Akira')
+        """
+        return self.random_element(self.first_name_male_pairs)
+
+    def first_name_female_pair(self):
+        """
+        @example ('明美', 'アケミ', 'Akemi')
+        """
+        return self.random_element(self.first_name_female_pairs)
+
+    def last_name_pair(self):
+        """
+        @example ('佐藤', 'サトウ', 'Sato')
+        """
+        return self.random_element(self.last_name_pairs)
+
+    def first_name(self):
+        """
+        @example '明美'
+        """
+        return self.first_name_pair()[0]
+
+    def first_name_male(self):
+        """
+        @example '晃'
+        """
+        return self.first_name_male_pair()[0]
+
+    def first_name_female(self):
+        """
+        @example '明美'
+        """
+        return self.first_name_female_pair()[0]
+
+    def last_name(self):
+        """
+        @example '佐藤'
+        """
+        return self.last_name_pair()[0]
 
     def first_kana_name(self):
-        '''
+        """
+        @example 'アケミ'
+        """
+        return self.first_name_pair()[1]
+
+    def first_kana_name_male(self):
+        """
         @example 'アキラ'
-        '''
-        return self.random_element(self.first_kana_names)
+        """
+        return self.first_name_male_pair()[1]
 
     def first_kana_name_female(self):
-        return self.random_element(self.first_kana_names_female)
-
-    def first_kana_name_male(self):
-        return self.random_element(self.first_kana_names_male)
+        """
+        @example 'アケミ'
+        """
+        return self.first_name_female_pair()[1]
 
     def last_kana_name(self):
-        '''
-        @example 'アオタ'
-        '''
-        return self.random_element(self.last_kana_names)
-
-    def romanized_name(self):
-        '''
-        @example 'Akira Aota'
-        '''
-        pattern = self.random_element(self.romanized_formats)
-        return self.generator.parse(pattern)
+        """
+        @example 'サトウ'
+        """
+        return self.last_name_pair()[1]
 
     def first_romanized_name(self):
-        '''
+        """
+        @example 'Akemi'
+        """
+        return self.first_name_pair()[2]
+
+    def first_romanized_name_male(self):
+        """
         @example 'Akira'
-        '''
-        return self.random_element(self.first_romanized_names)
+        """
+        return self.first_name_male_pair()[2]
 
     def first_romanized_name_female(self):
-        return self.random_element(self.first_romanized_names_female)
-
-    def first_romanized_name_male(self):
-        return self.random_element(self.first_romanized_names_male)
+        """
+        @example 'Akemi'
+        """
+        return self.first_name_female_pair()[2]
 
     def last_romanized_name(self):
-        '''
-        @example 'Aota'
-        '''
-        return self.random_element(self.last_romanized_names)
+        """
+        @example 'Sato'
+        """
+        return self.last_name_pair()[2]
+
+    def kana_name(self):
+        """
+        @example 'サトウ アケミ'
+        """
+        pattern = self.random_element(self.kana_formats)
+        return self.generator.parse(pattern)
+
+    def kana_name_male(self):
+        """
+        @example 'サトウ アキラ'
+        """
+        pattern = self.random_element(self.kana_formats_male)
+        return self.generator.parse(pattern)
+
+    def kana_name_female(self):
+        """
+        @example 'サトウ アケミ'
+        """
+        pattern = self.random_element(self.kana_formats_female)
+        return self.generator.parse(pattern)
+
+    def romanized_name(self):
+        """
+        @example 'Akemi Sato'
+        """
+        pattern = self.random_element(self.romanized_formats)
+        return self.generator.parse(pattern)
+
+    def romanized_name_male(self):
+        """
+        @example 'Akira Sato'
+        """
+        pattern = self.random_element(self.romanized_formats_male)
+        return self.generator.parse(pattern)
+
+    def romanized_name_female(self):
+        """
+        @example 'Akemi Sato'
+        """
+        pattern = self.random_element(self.romanized_formats_female)
+        return self.generator.parse(pattern)
diff --git a/faker/providers/person/ru_RU/__init__.py b/faker/providers/person/ru_RU/__init__.py
index 2234c86d..08ba094c 100644
--- a/faker/providers/person/ru_RU/__init__.py
+++ b/faker/providers/person/ru_RU/__init__.py
@@ -309,11 +309,7 @@ class Provider(PersonProvider):
         return self.random_element(self.middle_names)
 
     def middle_name_male(self):
-        if hasattr(self, 'middle_names_male'):
-            return self.random_element(self.middle_names_male)
-        return self.middle_name()
+        return self.random_element(self.middle_names_male)
 
     def middle_name_female(self):
-        if hasattr(self, 'middle_names_female'):
-            return self.random_element(self.middle_names_female)
-        return self.middle_name()
+        return self.random_element(self.middle_names_female)
diff --git a/faker/providers/person/th_TH/__init__.py b/faker/providers/person/th_TH/__init__.py
index c84dc49e..0f8aacf0 100644
--- a/faker/providers/person/th_TH/__init__.py
+++ b/faker/providers/person/th_TH/__init__.py
@@ -5,11 +5,23 @@ from .. import Provider as PersonProvider
 
 class Provider(PersonProvider):
     # weights are arbitrarily assigned
-    formats = OrderedDict((
-        ("{{first_name}} {{last_name}}", 0.97),
-        ("{{prefix}}{{first_name}} {{last_name}}", 0.015),
-        ("{{prefix}}{{first_name}} {{last_name}} {{suffix}}", 0.02),
-        ("{{first_name}} {{last_name}} {{suffix}}", 0.005),
+    formats_female = OrderedDict((
+        ('{{first_name_female}} {{last_name}}', 0.97),
+        ('{{prefix_female}}{{first_name_female}} {{last_name}}', 0.015),
+        ('{{first_name_female}} {{last_name}} {{suffix_female}}', 0.001),
+        ('{{prefix_female}}{{first_name_female}} {{last_name}} {{suffix}}', 0.001),
+    ))
+    formats_male = OrderedDict((
+        ('{{first_name_male}} {{last_name}}', 0.97),
+        ('{{prefix_male}}{{first_name_male}} {{last_name}}', 0.015),
+        ('{{first_name_male}} {{last_name}} {{suffix_male}}', 0.001),
+        ('{{prefix_male}}{{first_name_male}} {{last_name}} {{suffix}}', 0.001),
+    ))
+    formats_nonbinary = OrderedDict((
+        ('{{first_name_nonbinary}} {{last_name}}', 0.97),
+        ('{{prefix_nonbinary}}{{first_name_nonbinary}} {{last_name}}', 0.015),
+        ('{{first_name_nonbinary}} {{last_name}} {{suffix_nonbinary}}', 0.001),
+        ('{{prefix_nonbinary}}{{first_name_nonbinary}} {{last_name}} {{suffix}}', 0.001),
     ))
 
     # Thai prefix, adapted from
@@ -72,7 +84,6 @@ class Provider(PersonProvider):
         ("หม่อมราชวงศ์", 0.0001),
         ("หม่อมหลวง", 0.0001),
     ))
-
     prefixes_male = OrderedDict((
         ("นาย", 0.6),
         ("ด.ช.", 0.3),
@@ -140,649 +151,831 @@ class Provider(PersonProvider):
         ("พระใบฎีกา", 0.00001),
         ("เจ้าอธิการ", 0.00001),
     ))
+    prefixes_nonbinary = OrderedDict((
+        ("จ.ต.", 0.001),
+        ("จ.ท.", 0.001),
+        ("จ.ส.ต.", 0.001),
+        ("จ.ส.ท.", 0.001),
+        ("จ.ส.อ.", 0.001),
+        ("จ.อ.", 0.001),
+        ("ด.ต.", 0.001),
+        ("น.ต.", 0.001),
+        ("น.ท.", 0.001),
+        ("น.อ.", 0.001),
+        ("พ.จ.ต.", 0.001),
+        ("พ.จ.ท.", 0.001),
+        ("พ.จ.อ.", 0.001),
+        ("พ.ต.", 0.001),
+        ("พ.ต.ต.", 0.001),
+        ("พ.ต.ท.", 0.001),
+        ("พ.ต.อ.", 0.001),
+        ("พ.ท.", 0.001),
+        ("พ.อ.", 0.001),
+        ("พ.อ.ต.", 0.001),
+        ("พ.อ.ท.", 0.001),
+        ("พ.อ.อ.", 0.001),
+        ("ร.ต.", 0.001),
+        ("ร.ต.ต.", 0.001),
+        ("ร.ต.ท.", 0.001),
+        ("ร.ต.อ.", 0.001),
+        ("ร.ท.", 0.001),
+        ("ร.อ.", 0.001),
+        ("ส.ต.", 0.001),
+        ("ส.ต.ต.", 0.001),
+        ("ส.ต.ท.", 0.001),
+        ("ส.ต.อ.", 0.001),
+        ("ส.ท.", 0.001),
+        ("ส.อ.", 0.001),
+        ("พล.ต.", 0.0001),
+        ("พล.ต.ต.", 0.0001),
+        ("พล.ต.ท.", 0.0001),
+        ("พล.ต.อ.", 0.0001),
+        ("พล.ท.", 0.0001),
+        ("พล.ร.ต.", 0.0001),
+        ("พล.ร.ท.", 0.0001),
+        ("พล.ร.อ.", 0.0001),
+        ("พล.อ.", 0.0001),
+        ("พล.อ.ต.", 0.0001),
+        ("พล.อ.ท.", 0.0001),
+        ("พล.อ.อ.", 0.0001),
+        ("ม.ร.ว.", 0.0001),
+        ("ม.ล.", 0.0001),
+        ("หม่อมราชวงศ์", 0.0001),
+        ("หม่อมหลวง", 0.0001),
+    ))
 
     prefixes = prefixes_female.copy()
     prefixes.update(prefixes_male)
 
-    # first name partially from
-    # Chulalongkorn University famous teacher & student first name
-    # https://th.wikipedia.org/wiki/%E0%B8%A3%E0%B8%B2%E0%B8%A2%E0%B8%99%E0%B8%B2%E0%B8%A1%E0%B8%9A%E0%B8%B8%E0%B8%84%E0%B8%84%E0%B8%A5%E0%B8%88%E0%B8%B2%E0%B8%81%E0%B8%88%E0%B8%B8%E0%B8%AC%E0%B8%B2%E0%B8%A5%E0%B8%87%E0%B8%81%E0%B8%A3%E0%B8%93%E0%B9%8C%E0%B8%A1%E0%B8%AB%E0%B8%B2%E0%B8%A7%E0%B8%B4%E0%B8%97%E0%B8%A2%E0%B8%B2%E0%B8%A5%E0%B8%B1%E0%B8%A2
-    # and
+    prefixes_nonbinary = prefixes.copy()
+
+    # get 250 female names and 250 male names randomly
+    # (with approximate fair distribution of length) from
     # https://github.com/PyThaiNLP/pythainlp/blob/dev/pythainlp/corpus/person_names_female_th.txt
     # https://github.com/PyThaiNLP/pythainlp/blob/dev/pythainlp/corpus/person_names_male_th.txt
-    first_names = (
-        "กมล",
-        "กรกันต์",
-        "กรรณิการ์",
-        "กริช",
-        "กฤชภร",
-        "กฤตยา",
-        "กฤษฎา",
-        "กฤษดา",
-        "กฤษนะ",
-        "กอบชัย",
-        "กอบศักดิ์",
-        "กัญรภัส",
-        "กันต์",
-        "กานธนิกา",
-        "การะเกด",
-        "กิตตินันท์",
-        "กิตติพงษ์",
-        "กุลนัดดา",
-        "กุลนิจ",
-        "กุศล",
-        "กุศล",
-        "กุสนี",
-        "เกริก",
-        "เกรียงไกร",
-        "เกรียงเดช",
+    first_names_female = (
+        "กนกเนตร",
+        "กวาง",
+        "กองสิน",
+        "กะดิรัตน์",
+        "กันตวรรณ",
+        "กิ่งแก้ว",
+        "กิติกานต์",
+        "กิติยาธรณ์",
+        "กุลปรียา",
+        "กุลภาวลัย",
+        "เกศรา",
         "เกษรา",
-        "เกษศิรินทร์",
-        "โกเมน",
-        "ขวัญข้าว",
-        "ขัตติยะ",
-        "ขัตติยา",
-        "เขมิณทรา",
-        "แขมมณี",
-        "คงสง",
-        "คณะณัฐ",
-        "คณาธิป",
-        "คณิต",
-        "คมกฤษ",
-        "คำแข่ง",
-        "คีรติ",
-        "งามนิตย์",
-        "จรรยานี",
-        "จักรพงศ์",
+        "แกมแพร",
+        "ใกล้รุ่ง",
+        "ขอดิเยาะ",
+        "เขมจิรา",
+        "คณภรณ์",
+        "คมคาย",
+        "คำ",
+        "จณิตตา",
+        "จณิสตา",
+        "จรรยพร",
+        "จริยฉัตร",
+        "จักรีรัตน์",
+        "จันทนา",
+        "จันทภา",
+        "จิณภัทตา",
+        "จิตตานันท์",
+        "จิตรลดา",
+        "จินต์จุฑา",
+        "จิราภรณ์",
+        "จิฬาภรณ์",
+        "จีราภรณ์",
+        "จุฑาภรณ์",
+        "จุฑารัตน์",
+        "ฉัตรปรียา",
+        "ชนิศา",
+        "ชรินทร์ทิพย์",
+        "ชลิดา",
+        "ชัญญานุนาย",
+        "ชัฎชา",
+        "ชิดชนก",
+        "ซูรัยดา",
+        "ซูไรดา",
+        "ซูฮัยดา",
+        "ฐิตาพร",
+        "ฐิติกุล",
+        "ฐิติณัฐฐา",
+        "ฐิติยาพร",
+        "ณภัทร",
+        "ณัฐญาดา",
+        "ณัฐติญา",
+        "ณัฐธภรณ์",
+        "ณัฐธิตา",
+        "ณัฐพิชา",
+        "ณัฐวรินทร",
+        "ณาร์รีมาน",
+        "ณิชนันท์",
+        "ณิชาภัทร",
+        "ดวงจันทร์",
+        "ดวงพร",
+        "ดวงสมร",
+        "ดารุนี",
+        "ตรีนุช",
+        "ทองสิริ",
+        "ทับทิม",
+        "ทานตะวัน",
+        "ทินพร",
+        "ทิพย์วารี",
+        "ทิพรดา",
+        "ทิมาภรณ์",
+        "เทพนารี",
+        "ธมลพรรณ",
+        "ธัชญา",
+        "ธัญญกัญญา",
+        "ธัญญามาศ",
+        "ธีริสรา",
+        "นพรัตน์",
+        "นพวรรณ",
+        "นภัสรินทร์",
+        "นราวรรณ",
+        "นรีกานต์",
+        "นรีรัตน์",
+        "นวรรษนันท์",
+        "นันทวรรณ",
+        "นันทิกานต์",
+        "นาตยา",
+        "นารดา",
+        "นาวีตา",
+        "น้ำเพชร",
+        "นิติยา",
+        "นิภา",
+        "นิวิลดาน",
+        "นุจรี",
+        "เนตรฤดี",
+        "บุญทิวา",
+        "บุญเทียน",
+        "บุญพา",
+        "เบญญาทิพย์",
+        "ปฐวีกานต์",
+        "ปภาวรินทร์",
+        "ประจิน",
+        "ประไพพักตร์",
+        "ประภัทร์สรณ์",
+        "ปริญญา",
+        "ปัญญาพร",
+        "ปัณณธร",
+        "ปาริตา",
+        "ปิ่นบุญญา",
+        "ปิยนาฎ",
+        "ปิยนุช",
+        "ปิยวดี",
+        "ปิยะชาติ",
+        "ผกาทิพย์",
+        "พชรภรณ์",
+        "พรชนก",
+        "พรชีวิน",
+        "พรเบญญา",
+        "พรปราณี",
+        "พรพิไล",
+        "พรรณปพร",
+        "พรสวรรค์",
+        "พลานุช",
+        "พัชรีนิษฐ์",
+        "พันเกล้า",
+        "พัสวี",
+        "พาดีล๊ะ",
+        "พาสุข",
+        "พิชญ์สินี",
+        "พิมพกานต์",
+        "พิมพ์ประภา",
+        "พิมพ์พิชญา",
+        "พิมพ์สุดา",
+        "พิมพ์สุตา",
+        "พิไลพร",
+        "พิศพรรณ",
+        "พีรภัทร์",
+        "เพชรมณี",
+        "เพ็ญพรรษา",
+        "เพ็ญยุภา",
+        "เพียงกมล",
+        "ฟารินี",
+        "ฟิรยา",
+        "ภัคชัญญา",
+        "ภัคศุภางค์",
+        "ภัทรนาฎ",
+        "ภัทราวุธ",
+        "ภานิณี",
+        "ภารวี",
+        "ภาสินี",
+        "มณียา",
+        "มนรัตน์",
+        "มนัญชยา",
+        "มลิวรรณ",
+        "มะลีวัลย์",
+        "มัตติกา",
+        "มาซีเตาะ",
+        "มารีนี",
+        "มาสิตะ",
+        "เมทนี",
+        "เมษา",
+        "ยนงคราญ",
+        "ยุภา",
+        "ยุลิน",
+        "เยาวรัตน์",
+        "โยธิการ์",
+        "รมิตา",
+        "รวิวาน",
+        "รอกีเย๊าะ",
+        "รอซีด๊ะ",
+        "รักชนก",
+        "รังสินี",
+        "ราณี",
+        "รูไกยะฮ์",
+        "โรสชา",
+        "ลักษมี",
+        "ลัดดา",
+        "วณัฐดา",
+        "วนาลี",
+        "วรดาพร",
+        "วรนาฎ",
+        "วรรณกร",
+        "วรรณนิสา",
+        "วรรณรัตน์",
+        "วรรณาต",
+        "วสิตา",
+        "วันชนก",
+        "วัลยา",
+        "วิเชียร",
+        "วีร์สุดา",
+        "ศจีกาญจน์",
+        "ศรินยา",
+        "ศศิธร",
+        "ศศินา",
+        "ศศิยา",
+        "ศศิรินทร์",
+        "ศิริเกศ",
+        "ศิริญา",
+        "ศิรินันท์",
+        "ศุภกรชนา",
+        "ศุภนุนาย",
+        "สมใจ",
+        "สมมล",
+        "สราญจิตต์",
+        "สโรชา",
+        "สหัสมณี",
+        "สายสุรีย์",
+        "สิราพร",
+        "สิริกานต์",
+        "สิริลัดดา",
+        "สิริ",
+        "สุกฤษตา",
+        "สุธาวี",
+        "สุธินันท์",
+        "สุปรานี",
+        "สุพัตร",
+        "สุพัตรา",
+        "สุภัทริดา",
+        "สุภาพร",
+        "สุภาลินี",
+        "สุมัชญา",
+        "สุรการณ์",
+        "สุรนีย์",
+        "โสภณิตา",
+        "โสภา",
+        "หรรษา",
+        "หฤทัย",
+        "อณัฐตา",
+        "อธิตยา",
+        "อเนชา",
+        "อรจิรา",
+        "อรพิณ",
+        "อริสรา",
+        "อรุณี",
+        "อลิษา",
+        "อัญชัญ",
+        "อัญชิษฐา",
+        "อัญธิกา",
+        "อัญพัชร์",
+        "อันธิกา",
+        "อาซือมะ",
+        "อาภัศรา",
+        "อารีย์",
+        "อาแอเสาะ",
+        "อำพร",
+        "อำไพ",
+        "อุดมลักษณ์",
+        "อุลัยพร",
+        "อุษณีย์",
+        "ฮามีย๊ะ",
+    )
+    first_names_male = (
+        "กรพนธ์",
+        "กระสุน",
+        "กฤตพร",
+        "กฤตเมธ",
+        "กวีฉัฏฐ",
+        "กษิดิฐ",
+        "กิติชัย",
+        "กิติวัฒน์",
+        "กุลเชษฐ",
+        "กุลดิลก",
+        "เกริกพล",
+        "เกษตร",
+        "เกษมชัย",
+        "เกียรติก้อง",
+        "เกียรติศักดิ์",
+        "โกมล",
+        "โกวิทย์",
+        "ขวัญรุ้ง",
+        "เขียว",
+        "คมกริบ",
+        "คมกฤชญ์",
+        "คมสัน",
+        "คำปลิว",
+        "คำมั่น",
+        "จด",
+        "จักรกฤนาย",
+        "จักรชัย",
         "จักรพันธ์",
-        "จันทร์พิมพ์",
-        "จันทรา",
-        "จันทิมา",
-        "จารุณี",
-        "จำเนียร",
-        "จำลอง",
-        "จิตติมา",
-        "จิระ",
-        "จิรัฐิติ",
-        "จีรศักดิ์",
-        "จุฑาวุฒิ",
-        "จุรินทร์",
-        "จุฬิน",
-        "ฉัตรปวีณ์",
-        "ฉัตรวัชร์",
-        "ฉันทวิชช์",
-        "ชญาภา",
-        "ชฎาทิพ",
-        "ชนกนันท์",
-        "ชนม์ทิดา",
-        "ชนาธิป",
-        "ชนิตา",
-        "ชนิสาร์",
-        "ชยกร",
-        "ชยาวุธ",
-        "ชยิศา",
-        "ชลวิไล",
-        "ชลอ",
-        "ชลิตา",
-        "ช่วงโชติ",
-        "ชวฤทธิ์",
-        "ชัชมาภรณ์",
-        "ชัญญานุช",
-        "ชัยชน",
-        "ชัยณรงค์",
-        "ชาญชัย",
-        "ชารีฟ",
-        "ชีวะเกตุ",
-        "ชุติรัตน์",
-        "ชุติวงศ์",
-        "ชูกัน",
-        "ชูเกียรติ",
-        "โชคชัย",
-        "โชติพิพัฒน์",
-        "ซัลมีซา",
-        "ฎาริกา",
-        "ฐนิตนันท์",
-        "ฐิตาชลีข์",
-        "ฐิติมา",
-        "ณชัย",
-        "ณภศศิ",
-        "ณรงค์",
-        "ณรงค์",
-        "ณรัณธกรณ์",
-        "ณัฐจักร",
-        "ณัฐฑิกานต์",
-        "ณัฐ",
-        "ณัฐวลัย",
-        "ณัฐสิทธิ์",
-        "ณัฐหทัย",
-        "ณัทกาญจน์",
-        "ณิชานันท์",
-        "ดวงใจ",
-        "ดวงเนตร",
-        "ดารณี",
-        "ดำริห์",
-        "ดุจฤดี",
-        "ดุสิตสิน",
-        "ดุสิตา",
-        "เดชดำรง",
-        "ติงสมิตร",
-        "เตชานันท์",
-        "ถาวร",
-        "เถลิงเดช",
-        "ทรงยศ",
-        "ทวิช",
-        "ทวีพงศ์",
-        "ทวียศ",
-        "ทองปาน",
-        "ทักษอร",
-        "เทียนบุญ",
-        "ธนกิจ",
-        "ธนชัย",
-        "ธนพร",
-        "ธนพล",
-        "ธนพันธ์",
-        "ธนะชัย",
-        "ธนันต์ธรญ์",
-        "ธนาธร",
-        "ธนิตพล",
-        "ธนู",
-        "ธภัทร",
-        "ธรณินทร์",
-        "ธวัชชัย",
-        "ธัชกร",
-        "ธัญชนก",
-        "ธัญญา",
-        "ธัญฤทธิ์",
-        "ธัญสิทธิ์",
-        "ธันย์ชนก",
+        "จำรัส",
+        "จิม",
+        "จิรวิทย์",
+        "จีรยุทธ",
+        "เจตธนากร",
+        "เจตพินิษฐ์",
+        "เจษฎากร",
+        "เจษฏาภรณ์",
+        "ใจกลาง",
+        "ฉลองชัย",
+        "เฉลิมพล",
+        "เฉลิมรัฐ",
+        "เฉลิมรัตน์",
+        "ชัชนันท์",
+        "ชัชเวศย์",
+        "เชิงชาย",
+        "โชคภาดล",
+        "โชติวุฒิ",
+        "ไชยภพ",
+        "ซุกรี",
+        "ฌาฆีภัตฐ์",
+        "ญาณพันธุ์",
+        "ฐิติวุฒิ",
+        "ณปภัช",
+        "ณัฐจศักดิ์",
+        "ณัฐศักดิ์",
+        "ณิชเชฏฐ์",
+        "ดิลก",
+        "ตอฮา",
+        "ถนอมชัย",
+        "เถลิงยศ",
+        "ทรรศนชัย",
+        "ทวีวัฒน์",
+        "ทองรัตน์",
+        "ทัตธน",
+        "ทินวัฒน์",
+        "เทพณรงค์",
+        "เทอดศักดิ์",
+        "เทียมศักดิ์",
+        "ธนกิตต์",
+        "ธนนนท์",
+        "ธนภณ",
+        "ธนวันต์",
+        "ธเนษฐ",
+        "ธมน",
+        "ธราวิทญ์",
+        "ธวัศชา",
         "ธารา",
-        "ธาราภูมิ",
-        "ธำรง",
-        "ธิติมา",
-        "ธิปัตยา",
-        "ธีมะ",
-        "ธีรภัทธ์",
-        "ธีรัตถ์",
+        "ธาเอก",
+        "ธีร์ธวันาย",
+        "ธีรลักษณ์",
+        "ธีรวัช",
+        "ธีรวุฒิ",
         "ธีราทัต",
-        "นงลักษณ์",
-        "นนทกานต์",
-        "นพเก้า",
-        "นภารัตน์",
-        "นฤเทพ",
-        "นลินี",
-        "นวลพรรณ",
-        "นันทวัฒน์",
-        "นันทศักดิ์",
-        "นันทิญา",
-        "นิติมา",
-        "นิติสิริ",
-        "นิธิวัฒน์",
-        "นิพนธ์",
-        "นิพาดา",
-        "นิรมล",
-        "นิรมล",
-        "นุชชาลี",
-        "นุชอนงค์",
-        "นูรฟานา",
-        "นูรูมัน",
-        "บดี",
-        "บรรจง",
-        "บวรศักดิ์",
-        "บุญเชียร",
-        "บุญถึง",
-        "บุญทอง",
-        "บุญพิทักษ์",
-        "บุญยงค์",
-        "บุญยอด",
-        "บุญเลื่อน",
-        "บุญส่ง",
-        "บุญเหนือ",
-        "บุรพรัตน์",
-        "บุษกร",
-        "บุหงา",
-        "ปกป้อง",
-        "ปฏิญญา",
-        "ปทีป",
-        "ปรมัตต์",
-        "ปรวรรษ",
-        "ประกายพรึก",
-        "ประดิษฐ์",
-        "ประเทืองวุฒิ",
-        "ประภัทร์",
-        "ประมวล",
-        "ประโมทย์",
-        "ประยูร",
-        "ประวีณมัย",
-        "ประเวช",
-        "ประสงค์",
+        "นนทกาญจน์",
+        "นพ",
+        "นภนต์",
+        "นัฐพล",
+        "นันทวุฒิ",
+        "นัสรุน",
+        "นาทภูวพัฒน์",
+        "นาย",
+        "นิชนันท์",
+        "นิติ",
+        "นิมุ",
+        "นิรันดร์",
+        "นิรุตต์",
+        "เนติลักษณ์",
+        "บุญเกิด",
+        "บุญญกัลป์",
+        "บุญญามี",
+        "บุญนพ",
+        "บุญเอก",
+        "ปฐม",
+        "ปรมินทร์",
+        "ประเดิม",
+        "ประยุทธ์",
+        "ประวี",
         "ประสิทธิ์",
-        "ประเสริฐศรี",
-        "ปราโมช",
-        "ปริศนา",
-        "ปรีชา",
-        "ปรียาพร",
-        "ปวีณ์นุช",
-        "ปวีณ์นุนาย",
+        "ประเสริฐ",
+        "ปรายกานต์",
         "ปวีณ",
-        "ปวีณ์สุดา",
-        "ปองภพ",
-        "ปัณย์วีร์",
-        "ปาจรีย์",
-        "ปาณิสรา",
-        "ปานจิตร",
-        "ปาลีรัตน์",
-        "ปิยณี",
-        "ปิยะชาติ",
-        "ปิยะพันธ์",
-        "ปิยะรัตน์",
-        "พงศ์พิสุทธิ์",
-        "พชร",
-        "พรสิทธิ์",
-        "พลอย",
-        "พสุธา",
-        "พัชชริน",
-        "พัชทนัน",
-        "พัชรศรี",
-        "พัชฤนาถ",
-        "พัฒนะชัย",
-        "พันธมิตร",
-        "พันธุ์เลิศ",
-        "พาดีล๊ะ",
-        "พาลุสุข",
-        "พิชยา",
-        "พิชัยยุทธ์",
-        "พิบูลย์รัฐ",
-        "พิมพ์มาดา",
-        "พิมพิกา",
-        "พิรุณรักษ์",
-        "พิศาล",
-        "พิสมัย",
-        "พิสิทธิ์",
-        "พุดตาล",
-        "พุทธชาด",
-        "เพ็ชรา",
-        "ไพฑูรย์",
-        "ไพบูลย์",
-        "ไพโรจน์",
-        "ไพศิษฐ์",
-        "ฟองสนาน",
-        "ภริดา",
-        "ภัทร",
-        "ภัทร",
-        "ภัทรวี",
-        "ภัทราคม",
-        "ภัทรียา",
-        "ภานุเดช",
-        "ภานุภาค",
-        "ภาวิตา",
-        "ภีรเดช",
-        "ภูมิไท",
-        "ภูมิพัฒน์",
-        "ภูมิ",
-        "มณฑิตา",
-        "มโน",
-        "มะบูรฮัน",
-        "มัณฑนา",
-        "มาธวี",
-        "มานพ",
-        "มาศดิตถ์",
-        "มาหะมะสายูตี",
-        "มิ่งขวัญ",
-        "มิตรศิลป์",
-        "มิรันตี",
-        "เมณฑกา",
-        "เมตตา",
-        "เมธินี",
-        "เมลิษา",
-        "เมษ",
-        "ยงยุทธ",
-        "ยรรยง",
-        "ยิ่งพันธ์",
-        "ยุทธนา",
-        "ยุวศิริ",
-        "โยฮัน",
-        "รวีภัทร์",
-        "รสสุคนธ์",
-        "รอแม",
-        "รังสิมาศ",
-        "รัชชาภร",
-        "รัชชา",
-        "รัชวิน",
-        "รัฐนันท์",
-        "รัมภ์รดา",
-        "เริงชัย",
-        "เรืองโรจน์",
-        "ฤทัย",
-        "ลักษณา",
-        "ลัดพลี",
-        "เลอศักดิ์",
-        "เลิศนภา",
-        "เลิศศักดิ์",
-        "ฦาไชย",
-        "วงศกร",
-        "วรพิศ",
-        "วรรณวรงค์",
-        "วรรณา",
-        "วรรณา",
-        "วรรษพร",
-        "วรวงค์",
-        "วรินทร",
-        "วรินทร",
-        "วรุธ",
-        "วศิน",
-        "วัฒนกร",
-        "วัฒนา",
-        "วันชัย",
+        "ปัณณวัชร",
+        "ปัตถพงษ์",
+        "ปิยบุตร",
+        "ปิยวัจน์",
+        "ปิยะนันท์",
+        "ปุณณรัตน์",
+        "แปลง",
+        "ผดุงชาติ",
+        "ผดุงพล",
+        "พงษ์นเรศ",
+        "พลภูมิ",
+        "พศร",
+        "พัชรพร",
+        "พันเทพ",
+        "พันธุ์เทพ",
+        "พิชาภพ",
+        "พิพิธธน",
+        "พีรพัฒน์",
+        "พีระพงศ์พันธ์",
+        "พุทธ",
+        "พุทธิพงษ์",
+        "เพทาย",
+        "ไพสิฐ",
+        "ภควัฒน์",
+        "ภัคชนน",
+        "ภานุพล",
+        "ภานุวัตร",
+        "ภาสวุฒิ",
+        "ภูมิปัญญา",
+        "ภูวรา",
+        "ภูวฤณ",
+        "ภูวัน",
+        "ภูวิช",
+        "มนัส",
+        "มะสูเกียน",
+        "มาโนชญ์",
+        "มารุด",
+        "มูฮัมหมัดอิมรอน",
+        "มูฮำมัด",
+        "ไมล์",
+        "ยศพงศ์",
+        "ยศพนต์",
+        "ยศวัฒน์",
+        "ยอดแมน",
+        "ยุศรอน",
+        "ยูซุฟ",
+        "รชตกร",
+        "รภัสพงษ์",
+        "รัฐพงษ์",
+        "ราชพฤกษ์",
+        "ราชันทร์",
+        "ราชัน",
+        "เรืองเกียรติ",
+        "ฤทธิ์ชกร",
+        "เลิศเดช",
+        "วรปรัชญ์",
+        "วรรณชนะชัย",
+        "วรศาสส์",
+        "วรินทธิ์ธร",
+        "วันฉัตร",
         "วัลลภ",
-        "วิจิตร",
-        "วิชชพัชร์",
-        "วิชัยยุตม์",
-        "วิชัย",
-        "วิทยา",
-        "วิภาวี",
-        "วิราภรณ์",
-        "วิรุฬห์รักษ์",
-        "วิษณุ",
-        "วิสิฐ",
-        "วีระพงษ์",
-        "วีระศักดิ์",
-        "ศจีพันธ์",
-        "ศรัณย์ทร",
-        "ศรีจิตรา",
-        "ศรีหล้า",
-        "ศศิวรรณ์",
-        "ศักดา",
-        "ศักดิ์ศิริ",
-        "ศิระรังษี",
-        "ศิริจิตร",
-        "ศิรินทร์ทิพย์",
-        "ศิริพร",
-        "ศิริพิชยา",
-        "ศิริวิมล",
-        "ศีลวัต",
-        "ศึกษา",
-        "ศุภดิตถ์",
-        "ศุภเดช",
-        "ศุภพงศ์",
-        "ศุรุท",
-        "เศรษฐศิริ",
-        "สกาวรัตน์",
-        "สดศรี",
-        "สนุก",
-        "สมพงษ์",
-        "สมพร",
-        "สมพล",
-        "สมภพ",
-        "สมรัตน์",
+        "วาร์มูฮำหมัด",
+        "วาสุเทพ",
+        "วิกิจ",
+        "วิชชากร",
+        "วิชา",
+        "วิถี",
+        "วิทูลย์",
+        "วิพุธ",
+        "วิรชัย",
+        "วิรศักดิ์",
+        "วิสาร",
+        "วีรชัย",
+        "วีระโชติ",
+        "วีระวัฒน์",
+        "วุฒิ",
+        "ไวพจน์",
+        "ศดิศ",
+        "ศภัคชคง",
+        "ศรลักษณ์",
+        "ศรายุธ",
+        "ศรีสวัสดิ์",
+        "ศิรณัฐ",
+        "ศุภชัย",
+        "ศุภาศิล",
+        "สนั่น",
+        "สมเกียรติ",
+        "สมนึก",
+        "สมปอง",
+        "สมพิศ",
         "สมหมาย",
-        "สมหวัง",
-        "สมัญญา",
-        "สมัย",
-        "สรสิทธิ์",
-        "สรุโฆษิต",
-        "สวรรยา",
+        "สรรเพชญ์",
+        "สรายุทธ",
+        "สัญชาน",
         "สันชัย",
-        "สันติ",
-        "สันติ",
-        "สาคร",
-        "สามารถ",
-        "สามารถ",
-        "สายทิพย์",
-        "สายัณห์",
-        "สาลินี",
-        "สาลูดิน",
-        "สาวนูรอนีย์",
-        "สำเร็จ",
-        "สำลี",
-        "สิครินทร์",
-        "สิทธิพงษ์",
-        "สิทธิหล่อ",
-        "สิทธีอมร",
-        "สิริพงษ์",
-        "สิริภาธร",
-        "สิริยากร",
-        "สิโรรส",
-        "สุกัญญา",
-        "สุจินันท์",
-        "สุชาดา",
-        "สุชีวะ",
-        "สุทธิชัย",
-        "สุทธิ",
-        "สุทัตตา",
-        "สุทาทิพย์",
-        "สุธรรม",
-        "สุธรรม",
-        "สุนทร",
-        "สุนิดา",
-        "สุนีย์",
-        "สุนีย์",
-        "สุพิชฌาย์",
-        "สุภเดช",
-        "สุภิญญา",
-        "สุภิษา",
-        "สุมล",
-        "สุรเกียรติ์",
-        "สุรพล",
-        "สุรภา",
-        "สุรางค์",
-        "สุริพล",
-        "สุวรรณ",
-        "สุวลักษณ์",
-        "สุวิชช์",
-        "สุวิชญ",
-        "สุวิชา",
-        "สุวิมล",
-        "สู่ขวัญ",
-        "เสมอกัน",
-        "เสริมคุณ",
-        "เสาวณี",
-        "เสาวภาพ",
-        "แสงสนิท",
-        "โสภา",
-        "หมอนชัย",
-        "หยุด",
-        "หรรษา",
-        "หฤหรรษ์",
-        "หลุยส์",
-        "หิรัญญา",
-        "อณัฐชัย",
+        "สันติราษฎร์",
+        "สิทธัญ",
+        "สิทธิชัย",
+        "สินสมุทร",
+        "สิรวัฒน์",
+        "สิริรัตน์",
+        "สีหราช",
+        "สุชิน",
+        "สุทกร",
+        "สุทธิณัฐ",
+        "สุทธิพจน์",
+        "สุพนธ์",
+        "สุรธัช",
+        "สุรนัย",
+        "สุรวัช",
+        "สุไฮลัน",
+        "เสรี",
+        "โสภณ",
+        "หรรษธร",
+        "หลักทรัพย์",
+        "หล้า",
+        "หลี",
+        "อชิตะวีร์",
+        "อณาวิน",
         "อดิสรณ์",
-        "อดิสรณ์",
-        "อธิรัตน์",
-        "อนันดา",
-        "อนันดา",
-        "อนันต์",
-        "อนิตษา",
-        "อนุมัติ",
-        "อนุรัตน์",
-        "อโนทัย",
-        "อภัสรดา",
-        "อภิชาต",
-        "อภิไท",
-        "อมรวิชช์",
-        "อมร",
-        "อมาลีนา",
-        "อรพรรณ",
-        "อรุโณชา",
-        "อ่องจริต",
-        "อ่อนสา",
-        "อ่อนอุษา",
-        "อังษณา",
-        "อัญชนา",
-        "อัฎฐพล",
-        "อับดุลบาซิร",
-        "อับดุลอาเด็ล",
-        "อัมพร",
-        "อัศม์เดนาย",
-        "อัษฎาวุธ",
-        "อาทิตยาพร",
-        "อาทิวราห์",
-        "อานีซะห์",
-        "อาภัสรา",
-        "อาภาภัทร",
-        "อิฐหรอเหม",
-        "อิทธิพงศ์",
-        "อุนนดา",
-        "เอกธนา",
-        "ไอยวริญท์",
-        "ฮัมเสียะ",
-        "ฮาวาติฟ",
+        "อธิวัตร",
+        "อนิวัฒน์",
+        "อนุบาล",
+        "อนุวัช",
+        "อภิลักษณ์",
+        "อมัด",
+        "อรรจน์",
+        "อัครพนธ์",
+        "อับดุลเลาะห์",
+        "อัษฏา",
+        "อาฮามัด",
+        "อินทรีย์",
+        "อิสรันดร์",
+        "เอกชัย",
+        "เอกวิทย์",
+        "เอกอธิพงษ์",
+        "เอนกพงศ์",
+        "โอภาส",
+        "ฮานาฟี",
+        "ฮาฟิต",
     )
 
+    first_names = first_names_male + first_names_female
+    first_names_nonbinary = first_names_male + first_names_female
+
     # last name that has given by senior officer
     # http://www.reurnthai.com/index.php?topic=5273.45
+    # also partially from
+    # https://github.com/PyThaiNLP/pythainlp/blob/dev/pythainlp/corpus/family_names_th.txt
     last_names = (
-        "ดำริห์ชอบ",
+        "กุมารบุญ",
+        "แก้วชลคราม",
+        "แก้วอยู่",
+        "ขอหมั่นกลาง",
+        "ขันธุลา",
+        "ขำเอนก",
+        "ขุนดำ",
+        "เขียวขุ้ย",
+        "เขียวอ่อน",
+        "คณานุรักษ์",
+        "คำลือ",
+        "งามพิเชษฐ์",
+        "จ้อยนุแสง",
+        "จันทา",
+        "จันอ้น",
+        "เจริญรัมย์",
+        "แจ้งสว่าง",
+        "ฉัตรอภิเที่ยงค่ำ",
+        "ฉัพพรรณธนกูร",
+        "ฉายแสง",
+        "ฉิมพาลี",
+        "ชำนาญวาด",
+        "ชุมวระ",
+        "เช้าวันดี",
+        "ไชยภา",
+        "ซาซุม",
+        "ซูสารอ",
+        "เณรานุสนธิ์",
         "ดวงทับทิม",
-        "ดิศดใน",
+        "ด้วงโสน",
         "ดัตพันธุ์",
-        "ดุษฎีวนิช",
+        "ดาตู",
+        "ดาบเงิน",
         "ดาบเพ็ชร์",
-        "ดิสกะประกาย",
-        "เดชคุ้ม",
         "ดาวกระจาย",
-        "ดาบเงิน",
+        "ดาวอร่าม",
+        "ดำริห์ชอบ",
+        "ดิศดใน",
+        "ดิสกะประกาย",
         "ดีตพันธุ์",
         "ดุริยพันธุ์",
-        "ดาวอร่าม",
+        "ดุษฎีวนิช",
+        "เดชคุ้ม",
         "เดชวา",
-        "ติระคมน์",
-        "ไตรบรรพ",
         "ตระกูลบุญ",
-        "เตมิยะเดช",
-        "ตวงทอง",
-        "แต้กุล",
-        "ตรีครุธพันธุ์",
-        "ตัณฑนุช",
-        "ตั้งกุลงาม",
         "ตระกูลไม้เรียง",
+        "ตราชู",
+        "ตรีครุธพันธุ์",
+        "ตรีเภรินทร์",
+        "ตวงทอง",
+        "ตวันเยี่ยม",
         "ตะละภัฏ",
+        "ตั้งกุลงาม",
         "ตั้งเผ่า",
-        "ตันเผ่า",
-        "เตชะกำพุ",
+        "ตั้งรบ",
+        "ตัณฑนุช",
         "ตัณสถิตย์",
-        "ตราชู",
-        "ตวันเยี่ยม",
-        "ตรีเภรินทร์",
         "ตันตราจิณ",
-        "ตั้งรบ",
-        "ถนัดกลึง",
+        "ตันเผ่า",
+        "ตันยา",
+        "ติณรัตน์",
+        "ติระคมน์",
+        "เตชะกำพุ",
+        "เตมิยะเดช",
+        "แต้กุล",
+        "ไตรบรรพ",
+        "ถนอมกุลบุตร",
+        "ถนอมพลกรัง",
+        "ถนอมพล",
         "ถนอมมนุษย์",
-        "ถนัดอักษร",
-        "ถนัดการยนต์",
-        "ถนัดหัดถกรรม",
-        "ถาวรายุศม์",
+        "ถนัดกลึง",
         "ถนัดการเขียน",
-        "ถาวรรัตน",
+        "ถนัดการยนต์",
+        "ถนัดเดินข่าว",
         "ถนัดพิมพการ",
-        "ถ้วนศรี",
-        "ถนอมพล",
-        "ถาวระวรณ์",
-        "ถนัดรบ",
-        "ถนอมกุลบุตร",
-        "ถมปัด",
         "ถนัดภาษา",
-        "ถนัดเดินข่าว",
+        "ถนัดรบ",
         "ถนัดรักษา",
+        "ถนัดหัดถกรรม",
+        "ถนัดอักษร",
+        "ถนัดอาวุธ",
         "ถนิมมาศ",
+        "ถมปัด",
         "ถมังรักษสัตว์",
-        "แถมธน",
+        "ถ้วนศรี",
         "ถะเกิงชศ",
+        "ถาวรรัตน",
+        "ถาวระวรณ์",
+        "ถาวรายุศม์",
         "ถิรสวัสดิ์",
-        "ถนัดอาวุธ",
         "ถุงเงิน",
-        "ทุมะบุตร์",
-        "ทองประดิฐ",
+        "แถมธน",
         "ทรงโกมล",
-        "ทัศนสุทธิ",
-        "ทหารแท้",
-        "ทองอยู่",
-        "ทำประดู่",
+        "ทรัพย์ธำรงค์",
         "ทรัพย์สาร",
-        "ทีฆะ",
+        "ทวนไชย์",
         "ทวนทอง",
-        "ไทยสุชาต",
-        "ทันยุค",
-        "ไทนิยม",
-        "ทองลาภ",
-        "ทองเนื้อดี",
-        "ทองแท้",
         "ทวีเดช",
-        "ทับทิมไทย",
+        "ทศโยธิน",
+        "ทหารแท้",
+        "ทองแท้",
+        "ทองเนื้อดี",
+        "ทองประดิฐ",
+        "ทองปากน้ำ",
+        "ทองลาภ",
         "ทองสินธุ์",
-        "ไทไชโย",
-        "ทวนไชย์",
+        "ทองสีไพล",
         "ทองสุกเลิศ",
+        "ทองอยู่",
+        "ทันยุค",
+        "ทับทิมไทย",
+        "ทัศนสุทธิ",
+        "ทำประดู่",
+        "ทีฆะ",
+        "ทุมะบุตร์",
+        "แท่นทอง",
+        "ไทไชโย",
+        "ไทนิยม",
         "ไทยแท้",
-        "ทองสีไพล",
-        "ธรรมนิยม",
+        "ไทยสุชาต",
         "ธนประทีป",
-        "ธรรมเมธา",
-        "ธุวะนุติ์",
-        "ธาราธร",
-        "ธีวร",
-        "ธัญเสถียร",
+        "ธนรักษ์",
         "ธนูปกรณ์",
-        "เธียรายัน",
+        "ธรรมทินนา",
+        "ธรรมนิยม",
+        "ธรรมเมธา",
         "ธรรมฤดี",
+        "ธรรมสถิตไพศาล",
+        "ธัญเสถียร",
         "ธัญาโภชน์",
-        "ธนรักษ์",
-        "ธูปะวิโรจน์",
+        "ธาราธร",
+        "ธีวร",
+        "ธุวะนุติ์",
         "ธูปหอม",
-        "แนวพนิช",
-        "นักสำหรวจ",
+        "ธูปะวิโรจน์",
+        "เธียรายัน",
+        "นกทอง",
+        "นครเทพ",
+        "นพคเชนทร์",
+        "นพตระกูล",
+        "นรวิทย์โชติกุล",
         "นฤทุกข์",
-        "นาฏคายี",
-        "เนื่องนนท์",
-        "น้ำทิพย์",
-        "เนื้อนุ่ม",
+        "นฤภัย",
         "นวลฉวี",
+        "นวลเพ็ง",
+        "นะวะมันดร",
+        "นักรบ",
+        "นักสำหรวจ",
+        "นับเนื่องนอ",
+        "นากกนก",
         "นาคพันธุ์",
-        "นำธวัช",
-        "แน่นดุจป้อม",
-        "เณรานุสนธิ์",
+        "นาควงษ์",
+        "นาคสุทิน",
+        "นาคะนคร",
+        "นาฏคายี",
+        "นาถะเดชะ",
+        "นาถะพินธุ",
+        "นานายน",
+        "นามขำ",
         "นามเสวตร",
-        "นิษประปัญจ์",
-        "นิระหานี",
-        "นิลสุวรรณ์",
-        "นักรบ",
+        "น้ำทิพย์",
+        "นำธวัช",
         "นิติสาขา",
+        "นิยมเซียม",
         "นิยมธรรม",
-        "นิลเสนา",
-        "หนุนสุข",
+        "นิยมสำหรวจ",
+        "นิระหานี",
+        "นิลวรรณ",
         "นิลวิมล",
-        "นฤภัย",
-        "นาถะเดชะ",
-        "นพตระกูล",
-        "นิยมเซียม",
-        "หนักแน่น",
-        "นามขำ",
-        "นานายน",
-        "นับเนื่องนอ",
-        "แนวพญา",
-        "นาถะพินธุ",
         "นิลสลัว",
-        "นะวะมันดร",
-        "นิลวรรณ",
-        "เนตร์มณี",
-        "นุตตาร",
-        "นิยมสำหรวจ",
-        "นกทอง",
-        "นุชแนวนุ่ม",
-        "นาคสุทิน",
-        "นพคเชนทร์",
-        "นาคะนคร",
+        "นิลสุวรรณ์",
+        "นิลเสนา",
         "นิละทัต",
-        "นาควงษ์",
-        "นากกนก",
-        "บุนยาภิสนท์",
-        "บุญญาภิรมย์",
-        "บุณยะภาชน์",
+        "นิษประปัญจ์",
+        "นุชแนวนุ่ม",
+        "นุตตาร",
+        "นุ่มกัน",
+        "เนตร์มณี",
+        "เนื่องนนท์",
+        "เนื้อนุ่ม",
+        "แน่นดุจป้อม",
+        "แนวพญา",
+        "แนวพนิช",
+        "บัวเผื่อน",
         "บินดี",
-        "บุนยะศัพท์",
-        "บุนยะตีรณะ",
+        "บุญญาภิรมย์",
         "บุญญาไลย์",
         "บุญบำรุง",
+        "บุญศล",
+        "บุญส่ง",
+        "บุณยะภาชน์",
+        "บุตดา",
+        "บุตราช",
+        "บุนยะตีรณะ",
+        "บุนยะศัพท์",
+        "บุนยาภิสนท์",
+        "ประจันตะเสน",
+        "ปรีชากุลเศรษฐ์",
+        "ปานสุวรรณ",
+        "ผลบุญ",
+        "พงศ์ฉบับนภา",
+        "พรมอ่อน",
+        "พรรษาสกุล",
+        "พรสีมา",
+        "พานเกล้า",
+        "พีระเพ็ญกุล",
+        "เพียยา",
+        "โพธิสัตย์",
+        "ภูภักดี",
+        "มนทอง",
+        "มิ่งขวัญ",
+        "เมืองสุข",
+        "ไม้แดง",
+        "ยะผา",
+        "ยางสวย",
+        "ยาปะโลหิต",
+        "เยาวธนโชค",
+        "ร่มธิติรัตน์",
+        "ราชมณี",
+        "เลขะพันธุ์",
+        "เลิศกิ่ง",
+        "วะคีมัน",
+        "วาทา",
+        "วิลาสินี",
+        "วุฑฒยากร",
+        "เวียงจันทึก",
+        "ศรทอง",
+        "ศรีตะวัน",
+        "ศรีธนะเวทย์",
+        "ศรีเผด็จ",
+        "ศรีวงค์",
+        "ศรีสัตย์",
+        "ศรีอุ่น",
+        "ศาสตร์ศิลป์",
+        "ศิวะวรเวท",
+        "สงประเสริฐ",
+        "สังข์กรด",
+        "สันตะวงศ์",
+        "สาระพันธ์",
+        "สุวรรณหงษ์",
+        "ไสยกิจ",
+        "หนักแน่น",
+        "หนุนสุข",
+        "หอมพิกุล",
+        "หอมสิน",
+        "หิรัญสาลี",
+        "แหยมศิริ",
+        "อัตตนาถ",
+        "อุ่นอก",
+        "อุลหัสสา",
     )
 
     # thai suffix that has given by the king
diff --git a/faker/providers/profile/en_US/__init__.py b/faker/providers/profile/en_US/__init__.py
index 677c9760..e7f101f0 100644
--- a/faker/providers/profile/en_US/__init__.py
+++ b/faker/providers/profile/en_US/__init__.py
@@ -1,5 +1,5 @@
-from .. import Provider as ProfileProvider
+from .. import Provider as ProfileProvider  # pragma: no cover
 
 
-class Provider(ProfileProvider):
+class Provider(ProfileProvider):  # pragma: no cover
     pass
diff --git a/faker/providers/python/en_US/__init__.py b/faker/providers/python/en_US/__init__.py
index 7420bfda..23d8b4ed 100644
--- a/faker/providers/python/en_US/__init__.py
+++ b/faker/providers/python/en_US/__init__.py
@@ -1,5 +1,5 @@
-from .. import Provider as PythonProvider
+from .. import Provider as PythonProvider  # pragma: no cover
 
 
-class Provider(PythonProvider):
+class Provider(PythonProvider):  # pragma: no cover
     pass
diff --git a/faker/providers/user_agent/en_US/__init__.py b/faker/providers/user_agent/en_US/__init__.py
index 9440601d..5d44acaf 100644
--- a/faker/providers/user_agent/en_US/__init__.py
+++ b/faker/providers/user_agent/en_US/__init__.py
@@ -1,5 +1,5 @@
-from .. import Provider as UserAgentProvider
+from .. import Provider as UserAgentProvider  # pragma: no cover
 
 
-class Provider(UserAgentProvider):
+class Provider(UserAgentProvider):  # pragma: no cover
     pass


Test patch:
diff --git a/tests/providers/test_bank.py b/tests/providers/test_bank.py
index 57b8acab..2addc1b9 100644
--- a/tests/providers/test_bank.py
+++ b/tests/providers/test_bank.py
@@ -12,6 +12,7 @@ from faker.providers.bank.fr_FR import Provider as FrFrBankProvider
 from faker.providers.bank.no_NO import Provider as NoNoBankProvider
 from faker.providers.bank.pl_PL import Provider as PlPlBankProvider
 from faker.providers.bank.pt_PT import Provider as PtPtBankProvider
+from faker.providers.bank.th_TH import Provider as ThThBankProvider
 from faker.providers.bank.tr_TR import Provider as TrTrBankProvider
 
 
@@ -233,3 +234,18 @@ class TestFrCh(TestDeCh):
 class TestItCh(TestDeCh):
     """Test it_CH bank provider"""
     pass
+
+
+class TestThTh:
+    """Test th_TH bank provider"""
+
+    def test_bban(self, faker, num_samples):
+        for _ in range(num_samples):
+            assert re.fullmatch(r"\d{10}", faker.bban())
+
+    def test_iban(self, faker, num_samples):
+        for _ in range(num_samples):
+            iban = faker.iban()
+            assert is_valid_iban(iban)
+            assert iban[:2] == ThThBankProvider.country_code
+            assert re.fullmatch(r"\d{2}\d{10}", iban[2:])
diff --git a/tests/providers/test_date_time.py b/tests/providers/test_date_time.py
index 4be1edcb..312a2ea2 100644
--- a/tests/providers/test_date_time.py
+++ b/tests/providers/test_date_time.py
@@ -314,6 +314,10 @@ class TestDateTime(unittest.TestCase):
         # test century
         assert self.fake.date_time_this_century(after_now=False, tzinfo=utc) <= datetime.now(utc)
         assert self.fake.date_time_this_century(before_now=False, after_now=True, tzinfo=utc) >= datetime.now(utc)
+        assert (
+            self.fake.date_time_this_century(before_now=False, after_now=False, tzinfo=utc).
+            replace(second=0, microsecond=0) == datetime.now(utc).replace(second=0, microsecond=0)
+        )
         # test decade
         assert self.fake.date_time_this_decade(after_now=False, tzinfo=utc) <= datetime.now(utc)
         assert self.fake.date_time_this_decade(before_now=False, after_now=True, tzinfo=utc) >= datetime.now(utc)
@@ -329,6 +333,10 @@ class TestDateTime(unittest.TestCase):
             self.fake.date_time_this_year(before_now=False, after_now=False, tzinfo=utc).
             replace(second=0, microsecond=0) == datetime.now(utc).replace(second=0, microsecond=0)
         )
+        assert (
+            self.fake.date_time_this_year(before_now=True, after_now=True, tzinfo=utc).
+            year == datetime.now(utc).year
+        )
         # test month
         assert self.fake.date_time_this_month(after_now=False, tzinfo=utc) <= datetime.now(utc)
         assert self.fake.date_time_this_month(before_now=False, after_now=True, tzinfo=utc) >= datetime.now(utc)
@@ -336,32 +344,56 @@ class TestDateTime(unittest.TestCase):
             self.fake.date_time_this_month(before_now=False, after_now=False, tzinfo=utc).
             replace(second=0, microsecond=0) == datetime.now(utc).replace(second=0, microsecond=0)
         )
+        assert (
+            self.fake.date_time_this_month(before_now=True, after_now=True, tzinfo=utc).
+            month == datetime.now(utc).month
+        ) and (
+            self.fake.date_time_this_month(before_now=True, after_now=True, tzinfo=utc).
+            year == datetime.now(utc).year
+        )
 
     @unittest.skipUnless(is64bit(), "requires 64bit")
     def test_date_this_period(self):
         # test century
+        assert (
+            self.fake.date_this_century(before_today=True, after_today=True).
+            strftime("%G")[:2] == datetime.now().strftime("%G")[:2]
+        )
         assert self.fake.date_this_century(after_today=False) <= date.today()
         assert self.fake.date_this_century(before_today=False, after_today=True) >= date.today()
+        assert self.fake.date_this_century(before_today=False, after_today=False) == date.today()
         # test decade
+        assert (
+            self.fake.date_this_decade(before_today=True, after_today=True).
+            strftime("%G")[:3] == datetime.now().strftime("%G")[:3]
+        )
         assert self.fake.date_this_decade(after_today=False) <= date.today()
         assert self.fake.date_this_decade(before_today=False, after_today=True) >= date.today()
         assert (
-            self.fake.date_this_decade(before_today=False, after_today=False)) == (
-            date.today()
+            self.fake.date_this_decade(before_today=False, after_today=False) == date.today()
         )
         # test year
+        assert (
+            self.fake.date_this_year(before_today=True, after_today=True).
+            year == datetime.now().year
+        )
         assert self.fake.date_this_year(after_today=False) <= date.today()
         assert self.fake.date_this_year(before_today=False, after_today=True) >= date.today()
         assert (
-            self.fake.date_this_year(before_today=False, after_today=False)) == (
-            date.today()
+            self.fake.date_this_year(before_today=False, after_today=False) == date.today()
         )
         # test month
+        assert (
+            self.fake.date_this_month(before_today=True, after_today=True).
+            month == datetime.now().month
+        ) and (
+            self.fake.date_this_month(before_today=True, after_today=True).
+            year == datetime.now().year
+        )
         assert self.fake.date_this_month(after_today=False) <= date.today()
         assert self.fake.date_this_month(before_today=False, after_today=True) >= date.today()
         assert (
-            self.fake.date_this_month(before_today=False, after_today=False)) == (
-            date.today()
+            self.fake.date_this_month(before_today=False, after_today=False) == date.today()
         )
 
     def test_date_time_between(self):
@@ -370,7 +402,14 @@ class TestDateTime(unittest.TestCase):
         _20_years_ago = change_year(now, -20)
 
         random_datetime = self.fake.date_time_between(start_date='-30y', end_date='-20y')
+        assert isinstance(random_datetime, datetime)
+        self.assertBetween(random_datetime, _30_years_ago, _20_years_ago)
 
+        now = datetime.now(tz=utc)
+        _30_years_ago = change_year(now, -30)
+        _20_years_ago = change_year(now, -20)
+
+        random_datetime = self.fake.date_time_between(start_date='-30y', end_date='-20y', tzinfo=utc)
         assert isinstance(random_datetime, datetime)
         self.assertBetween(random_datetime, _30_years_ago, _20_years_ago)
 
@@ -706,7 +745,7 @@ class DatesOfBirth(unittest.TestCase):
 
 
 class TestFilPh(unittest.TestCase):
-    num_sample_runs = 1000
+    num_sample_runs = 50
 
     def setUp(self):
         self.setup_constants()
@@ -722,11 +761,11 @@ class TestFilPh(unittest.TestCase):
         self.month_names = Provider.MONTH_NAMES.values()
 
     def test_PH_of_week(self):
-        for i in range(self.num_sample_runs):
+        for _ in range(self.num_sample_runs):
             assert self.fake.day_of_week() in self.day_names
 
     def test_PH_month_name(self):
-        for i in range(self.num_sample_runs):
+        for _ in range(self.num_sample_runs):
             assert self.fake.month_name() in self.month_names
 
 
@@ -856,6 +895,188 @@ class TestSkSk(unittest.TestCase):
         assert month in SkSkProvider.MONTH_NAMES.values()
 
 
+class TestThTh(unittest.TestCase):
+    num_sample_runs = 50
+
+    def setUp(self):
+        self.fake = Faker('th_TH')
+        Faker.seed(0)
+
+    def test_day(self):
+        day = self.fake.day_of_week()
+        assert isinstance(day, str)
+        assert day.startswith("วัน")
+
+    def test_month(self):
+        month = self.fake.month_name()
+        assert isinstance(month, str)
+
+    def test_date(self):
+        # default format is "%-d %b %Y"
+        # (date with no padding, abbreviated month, full year [4 digits])
+        date = self.fake.date(thai_digit=True)
+        for _ in range(self.num_sample_runs):
+            assert re.fullmatch(
+                    r'[๐-๙]{1,2} '
+                    r'(ม\.ค\.|ก\.พ\.|มี\.ค\.|เม\.ย\.|พ\.ค\.|มิ\.ย\.|ก\.ค\.|ส\.ค\.|ก\.ย\.|ต\.ค\.|พ\.ย\.|ธ\.ค\.) '
+                    r'[๐-๙]{4}',
+                    date,
+                )
+
+    def test_time(self):
+        time = self.fake.time(thai_digit=True)
+        for _ in range(self.num_sample_runs):
+            assert re.fullmatch(r'[๐-๙]{2}:[๐-๙]{2}:[๐-๙]{2}', time)
+
+    def test_century(self):
+        century = self.fake.century()
+        assert isinstance(century, str)
+        assert len(century) <= 2
+        century = self.fake.century(thai_digit=True)
+        for _ in range(self.num_sample_runs):
+            assert re.fullmatch(r'[๑-๒]?[๐-๙]', century)
+
+    def test_date_pattern(self):
+        # unsupported or incomplete directive
+        date = self.fake.date("%Q")
+        assert date == "Q"
+        date = self.fake.date("%%")
+        assert date == "%"
+        date = self.fake.date("%-")
+        assert date == "-"
+        date = self.fake.date("% ")
+        assert date == " "
+        date = self.fake.date("%0")
+        assert date == "0"
+        date = self.fake.date("%")
+        assert date == "%"
+
+        # may be not supported on Windows, try for coverage
+        date = self.fake.date("%s")
+        date = self.fake.date("%f")
+
+        # National representation of the full weekday name
+        date = self.fake.date("%A")
+        assert isinstance(date, str)
+
+        # National representation of the abbreviated weekday
+        date = self.fake.date("%a")
+        assert isinstance(date, str)
+        assert len(date) <= 2
+
+        # National representation of the full month name
+        date = self.fake.date("%B")
+        assert isinstance(date, str)
+        assert "." not in date
+
+        # National representation of the abbreviated month name
+        date = self.fake.date("%b")
+        assert isinstance(date, str)
+        assert "." in date
+
+        # Century as decimal number
+        date = self.fake.date("%C")
+        assert isinstance(date, str)
+
+        # Locale’s appropriate date and time representation
+        # พ   6 ต.ค. 01:40:00 2519  <-- left-aligned weekday, right-aligned day
+        date = self.fake.date("%c")
+        assert isinstance(date, str)
+
+        # Equivalent to ``%m/%d/%y''
+        date = self.fake.date("%D")
+        assert isinstance(date, str)
+
+        # Equivalent to ``%Y-%m-%d''
+        date = self.fake.date("%F")
+        assert isinstance(date, str)
+
+        # ISO 8601 year with century representing the year that contains
+        # the greater part of the ISO week (%V). Monday as the first day
+        # of the week.
+        date = self.fake.date("%G")
+        assert isinstance(date, str)
+
+        # Same year as in ``%G'',
+        # but as a decimal number without century (00-99).
+        date = self.fake.date("%g")
+        assert isinstance(date, str)
+        assert len(date) <= 2
+
+        # BSD extension, ' 6-ต.ค.-2519'
+        date = self.fake.date("%v")
+        assert isinstance(date, str)
+
+        # Locale’s appropriate time representation.
+        date = self.fake.date("%X")
+        assert isinstance(date, str)
+
+        # Locale’s appropriate date representation.
+        date = self.fake.date("%x")
+        assert isinstance(date, str)
+
+        # Year with century
+        date = self.fake.date("%Y")
+        assert isinstance(date, str)
+
+        # Year without century
+        date = self.fake.date("%y")
+        assert isinstance(date, str)
+        assert len(date) <= 2
+
+        # National representation of the date and time
+        # (the format is similar to that produced by date(1))
+        # Wed  6 Oct 1976 01:40:00
+        date = self.fake.date("%+")
+        assert isinstance(date, str)
+
+        # GNU libc extension,
+        # no padding
+        for _ in range(self.num_sample_runs):
+            date = self.fake.date("%-d")
+            assert isinstance(date, str)
+            assert date[0] != "0"
+
+        # GNU libc extension,
+        # explicitly specify space (" ") for padding
+        for _ in range(self.num_sample_runs):
+            date = self.fake.date("%_d")
+            assert isinstance(date, str)
+            assert date[0] != "0"
+
+        # GNU libc extension,
+        # explicitly specify zero ("0") for padding
+        for _ in range(self.num_sample_runs):
+            date = self.fake.date("%0v")
+            assert isinstance(date, str)
+            assert date[0] != " "
+
+        # GNU libc extension,
+        # convert to upper case
+        date = self.fake.date("%^p")
+        assert isinstance(date, str)
+        assert date.isupper()
+
+        # GNU libc extension,
+        # swap case - useful for %Z
+        date = self.fake.date("%#p")
+        assert isinstance(date, str)
+        assert date.islower()
+
+        # POSIX extension,
+        # uses the locale's alternative representation
+        # Not implemented yet
+        # swap case - useful for %Z
+        date = self.fake.date("%Ed")
+        assert isinstance(date, str)
+
+        # POSIX extension,
+        # uses the locale's alternative numeric symbols
+        date = self.fake.date("%Od")
+        assert isinstance(date, str)
+        assert date[0] not in "0123456789"
+
+
 class TestTrTr(unittest.TestCase):
 
     def setUp(self):
diff --git a/tests/providers/test_misc.py b/tests/providers/test_misc.py
index 7822eb54..d51d80c3 100644
--- a/tests/providers/test_misc.py
+++ b/tests/providers/test_misc.py
@@ -651,3 +651,15 @@ class TestMiscProvider:
         with pytest.raises(TypeError) as excinfo:
             faker_with_foobar.fixed_width(**kwargs)
         assert str(excinfo.value) == 'Invalid arguments type. Must be a dictionary'
+
+    def test_md5(self, faker):
+        assert isinstance(faker.md5(), str)
+        assert isinstance(faker.md5(raw_output=True), bytes)
+
+    def test_sha1(self, faker):
+        assert isinstance(faker.sha1(), str)
+        assert isinstance(faker.sha1(raw_output=True), bytes)
+
+    def test_sha256(self, faker):
+        assert isinstance(faker.sha256(), str)
+        assert isinstance(faker.sha256(raw_output=True), bytes)
diff --git a/tests/providers/test_person.py b/tests/providers/test_person.py
index a90ae978..ec7bb910 100644
--- a/tests/providers/test_person.py
+++ b/tests/providers/test_person.py
@@ -142,6 +142,26 @@ class TestJaJP(unittest.TestCase):
         assert last_romanized_name
         assert isinstance(last_romanized_name, str)
 
+        first_name_pair = self.fake.first_name_pair()
+        assert first_name_pair
+        assert len(first_name_pair) == 3
+        assert all(map(lambda s: isinstance(s, str), first_name_pair))
+
+        first_name_male_pair = self.fake.first_name_male_pair()
+        assert first_name_male_pair
+        assert len(first_name_male_pair) == 3
+        assert all(map(lambda s: isinstance(s, str), first_name_male_pair))
+
+        first_name_female_pair = self.fake.first_name_female_pair()
+        assert first_name_female_pair
+        assert len(first_name_female_pair) == 3
+        assert all(map(lambda s: isinstance(s, str), first_name_female_pair))
+
+        last_name_pair = self.fake.last_name_pair()
+        assert last_name_pair
+        assert len(last_name_pair) == 3
+        assert all(map(lambda s: isinstance(s, str), last_name_pair))
+
 
 class TestNeNP(unittest.TestCase):
 
diff --git a/tests/providers/test_profile.py b/tests/providers/test_profile.py
new file mode 100644
index 00000000..1312fdf2
--- /dev/null
+++ b/tests/providers/test_profile.py
@@ -0,0 +1,50 @@
+import unittest
+
+from faker import Faker
+
+
+class TestProfileProvider(unittest.TestCase):
+    """Test profile provider methods"""
+
+    num_samples = 10
+
+    def setUp(self):
+        self.fake = Faker()
+        Faker.seed(0)
+
+    def test_simple_profile(self):
+        for _ in range(self.num_samples):
+            profile = self.fake.simple_profile()
+            assert isinstance(profile, dict)
+            assert len(profile["username"]) >= 1
+            assert profile["sex"] in ["F", "M"]
+
+        profile = self.fake.simple_profile(sex="F")
+        assert profile["sex"] == "F"
+        profile = self.fake.simple_profile(sex="M")
+        assert profile["sex"] == "M"
+
+    def test_profile(self):
+        for _ in range(self.num_samples):
+            profile = self.fake.profile()
+            assert isinstance(profile, dict)
+            assert len(profile["username"]) >= 1
+            assert profile["sex"] in ["F", "M"]
+            assert "website" in profile.keys()
+
+        profile = self.fake.profile(sex="F")
+        assert profile["sex"] == "F"
+        profile = self.fake.profile(sex="M")
+        assert profile["sex"] == "M"
+
+        profile = self.fake.profile(fields=["ssn", "name"])
+        assert len(profile) == 2
+        assert "ssn" in profile.keys()
+        assert "name" in profile.keys()
+
+        profile = self.fake.profile(fields=[])
+        assert len(profile) > 0
+        assert "ssn" in profile.keys()
+
+        profile = self.fake.profile(fields=["secret_org"])
+        assert len(profile) == 0