Skip to content

Clock date parsing returns wrong year on non-Gregorian calendar locales #3984

Description

@apexpdl

Describe the bug

On a Thai-language Android or iPhone, the Clock component reads dates with the wrong year. Calling Clock.MakeInstant("06/10/2026") and asking for the year back returns 1483 instead of 2026. This breaks any app that saves and reloads dates, runs countdowns, calculates ages, or schedules alarms.

This is the same class of bug fixed in #3891 (Chart date formatters), but in the Clock component, which has much broader reach since it's used in nearly every tutorial that touches time.

appinventor/components/src/com/google/appinventor/components/runtime/util/Dates.java creates SimpleDateFormat instances without a Locale in three places:

  • Line 148, tryParseDate — used by Clock.MakeInstant, Clock.MakeInstantFromMillis, and Clock.MakeInstantFromParts when parsing a string.
  • Line 202, FormatDateTime.
  • Line 222, FormatDate.

On devices set to a Thai locale, SimpleDateFormat resolves against the Buddhist calendar. Parsing is the dangerous side: Clock.MakeInstant("06/10/2026") reads 2026 as a Buddhist Era year, which is Gregorian year 1483. Any app that parses a date string (saved data, hardcoded dates, user input) silently gets an instant about 543 years in the past. Format has the mirror problem — Clock.FormatDate produces a Buddhist-year string, which then round-trips wrong.

The same root cause exists on iOS. appinventor/components-ios/src/Clock.swift line 16 sets date.locale = Locale.preferredLanguage, so a Thai-language iPhone hits the same wrong-calendar parsing.

Note this should not affect the WeekdayName / MonthName style functions, which intentionally use the device locale for display names and should keep their current behavior.

Also worth flagging: tryParseDate swallows ParseException silently (catch (ParseException e) {} on line 149), so when parsing fails it produces an IllegalArgumentException with no underlying detail. I'll surface the underlying error in the same PR so any remaining locale-related parse failures are debuggable.

Affects

  • Android Companion
  • iOS Companion
  • Android Compiled APK/AAB
  • iOS Compiled IPA

Expected behavior

Clock.MakeInstant with one of the documented format strings (e.g. MM/dd/yyyy) should produce the same instant on every device, regardless of locale. Format and parse should round-trip on every locale.

Steps to reproduce

  1. Set an Android device or emulator to Thai (Settings > System > Languages > Thai).
  2. In a test app, call Clock.MakeInstant("06/10/2026") then Clock.Year(...) on the result.
  3. Expected: 2026. Actual: 1483.

I have a fix ready following the same approach approved in #3891 and will open PRs for both Android and iOS.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions