2

For an Android app, I need to parse date in Thai local format (as like, year 2019 should be returned as 2562). I do not understand how can I do so. Currently using SimpleDateFormatter to parse the date in default local format.

fun adjustTimePattern(dateString: String, oldPattern: String, newPattern: String): String? {
    val dateFormat = SimpleDateFormat(oldPattern, Locale.getDefault())
    dateFormat.timeZone = TimeZone.getTimeZone("UTC")
    return try {
        val calendar = Calendar.getInstance()
        calendar.time = dateFormat.parse(dateString)
        val newFormat = SimpleDateFormat(newPattern, Locale.getDefault())
        newFormat.format(calendar.time)
    } catch (e: ParseException) {
        return null
    }
}

Tried to hardcode the value of locale (used Locale("th", "TH") instead of Locale.getDefault()), but got luck since SimpleDateFormat class uses Gregorian Calendar itself.

Have tried to use LocalDate & DateTimeFormatter as well, but the year value doesn't change by any means.

fun formatTime(pattern: String): String {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val formatter = DateTimeFormatter.ofPattern(pattern, Locale("th", "TH"))
        LocalDate.now().format(formatter)
    } else {
        ""
    }
}

.

Can anyone help me out on this?

Sudip Podder
  • 830
  • 11
  • 25
  • 3
    You should prefer the classes from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). However a `LocalDate` is inherently a date in the ISO/proleptic Gregorian calendar, so won’t work for Thai dates. The answer shows a solution that I think is great. – Ole V.V. Oct 24 '19 at 12:23

2 Answers2

4

ThaiBuddhistDate class

You can use a java.time.chrono.ThaiBuddhistDate to get this done, see the following example:

public static void main(String[] args) throws ParseException {
    ThaiBuddhistDate tbd = ThaiBuddhistDate.now(ZoneId.systemDefault());
    System.out.println(tbd.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}

The output I get on my system is

2562-10-24

Most java.time functionality is back-ported to Java 6 & Java 7 in the ThreeTen-Backport project. Further adapted for earlier Android (<26) in ThreeTenABP. See How to use ThreeTenABP….

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
deHaar
  • 17,687
  • 10
  • 38
  • 51
  • @SudipPodder Yes, see [this question](https://stackoverflow.com/questions/38922754/how-to-use-threetenabp-in-android-project). You basically have to use a support library and that question is about how to use it in Android. – deHaar Oct 24 '19 at 13:21
  • 1
    Definitely will give a shot. If it works, will mark yours as the accepted answer. You can edit your answer and add the comment's link as well as a support for API Level < 26. – Sudip Podder Oct 24 '19 at 13:31
  • 1
    @BasilBourque OP had done that and I removed the Android tag because I thought it was only about java.time. I wouldn't have removed that tag if it had been possible to write more than 5 tags below a question. – deHaar Oct 24 '19 at 13:45
  • 2
    I added a mention of Android at start of Question. – Basil Bourque Oct 24 '19 at 13:46
  • @BasilBourque Thanks, OP has replaced the Date tag with Android. – deHaar Oct 24 '19 at 13:47
  • 1
    @SudipPodder As long as you don't have years before 1941 (gregorian) this solution (based on ThreetenABP) will work fine. – Meno Hochschild Oct 24 '19 at 17:48
  • @deHaar, facing issue if the formatting pattern contains HH:mm:ss value. Seems like HH:mm:ss format is not supported in ThaiBuddhistDate. Any idea how can it be handled? – Sudip Podder Oct 28 '19 at 18:29
  • @SudipPodder that class holds information about the date only. Maybe obtain the datetime from an instant and use [`ChronoZonedDateTime`](https://docs.oracle.com/javase/8/docs/api/java/time/chrono/ThaiBuddhistChronology.html#zonedDateTime-java.time.Instant-java.time.ZoneId-), but I'm not quite sure... There might be other options. – deHaar Oct 28 '19 at 19:02
0

Since you're already using java.util.Calendar and java.text.SimpleDateFormat.

If you can change locale while instantiating your Calendar, this should work:

val thaiCalendar = Calendar.getInstance(Locale("th", "TH"))
println(thaiCalendar.get(Calendar.YEAR)) // prints 2562

But, if you just want to change the format, this worked for me:

val notThaiCalendar = Calendar.getInstance()
val thaiFormatter = SimpleDateFormat("yyyy-MM-dd", Locale("th", "TH"))
println(thaiFormatter.format(notThaiCalendar.time)) // prints 2562-10-24

EDIT

This solution was not tested on Android

Diego Magdaleno
  • 831
  • 8
  • 20
  • 1
    FYI, the terribly flawed date-time classes such as [`java.util.Date`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/tutorial/datetime/TOC.html) classes built into Java 8 and later. – Basil Bourque Oct 24 '19 at 13:35
  • I know, but he is using these classes in his code on method `adjustTimePattern` – Diego Magdaleno Oct 24 '19 at 13:42
  • will check it @DiegoMagdaleno – Sudip Podder Oct 24 '19 at 13:58
  • 1
    Android (on most mobile platforms) has a different `Calendar`-implementation than old Java, especially the Buddhist calendar is missing, so this answer will probably not work. – Meno Hochschild Oct 24 '19 at 17:47
  • @MenoHochschild i really didn't test it on Android. I didn't know there was such a difference. – Diego Magdaleno Oct 24 '19 at 17:55
  • @DiegoMagdaleno While using the library that was used in the question makes sense in many cases, this questioner is also using `DateTimeFormatter` and `LocalDate` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/), so in this case I think it’s better to build on that and not on the old and poorly designed classes also mentioned. – Ole V.V. Oct 25 '19 at 02:54