Skip to content

Bug: day&month formatting doesn't match current locale #500

@AndroidDeveloperLB

Description

@AndroidDeveloperLB

In many locales, the way the day&month is shown is different from what is chosen on the library and sample.

It's not always "M/d" as such:

image

Sometimes it's "d/M", and sometimes the "/" is replaced with something different, like "-" or even "." .

I think this is a better solution to have a numeric formatting of day&month:

/**returns a numeric date format of day&month, based on the current locale.
 * This is important, as the format is different in many countries. Can be "d/M", "M/d", "d-M", "M-d" ,...*/
@JvmStatic
fun getNumericDayAndMonthFormat(context: Context): SimpleDateFormat {
    val defaultDateFormatPattern = "d/M"
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        val locale = Locale.getDefault()
        var bestDateTimePattern = DateFormat.getBestDateTimePattern(locale, defaultDateFormatPattern)
        //workaround fix for this issue: https://issuetracker.google.com/issues/79311044
        //TODO if there is a better API that doesn't require this workaround, use it. Be sure to check vs all locales, as done here: https://issuetracker.google.com/issues/37044127
        bestDateTimePattern = bestDateTimePattern.replace("d+".toRegex(), "d").replace("M+".toRegex(), "M")
        return SimpleDateFormat(bestDateTimePattern, locale)
    }
    try {
        val dateFormatOrder = DateFormat.getDateFormatOrder(context)
        if (dateFormatOrder.isEmpty())
            return SimpleDateFormat(defaultDateFormatPattern, Locale.getDefault())
        val sb = StringBuilder()
        for (i in dateFormatOrder.indices) {
            val c = dateFormatOrder[i]
            if (Character.toLowerCase(c) == 'y')
                continue
            if (sb.isNotEmpty())
                sb.append('/')
            when (Character.toLowerCase(c)) {
                'm' -> sb.append("M")
                'd' -> sb.append("d")
            }
        }
        val dateFormatString = sb.toString()
        return SimpleDateFormat(dateFormatString, Locale.getDefault())
    } catch (e: Exception) {
        return SimpleDateFormat(defaultDateFormatPattern, Locale.getDefault())
    }
}

Even in my solution I had to have some workaround, because the formatting that Android provides sometimes puts a longer format, as I wrote here. If there is a better solution, please let me know, and check it with all locales. Example of testing of what I wrote can be done as such:

    val date = Date()
    for (locale in Locale.getAvailableLocales()) {
        val bestDateTimePattern = android.text.format.DateFormat.getBestDateTimePattern(locale, "d/M").replace("d+".toRegex(), "d").replace("M+".toRegex(), "M")
        val formattedString = android.text.format.DateFormat.format(bestDateTimePattern, date).toString()
        Log.d("AppLog", "best: locale:$locale bestDateTimePattern:$bestDateTimePattern formatted:$formattedString")
    }

Looking at the results, I think all look ok.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions