i try to implement a simple UTC time for all the world…
I thought i had succeed. But recently i updated from panda 1 to panda 2 ( android studio ) and my code doesn’t work anymore.
Here is a simple code that used to work:
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
fun main() {
var now = Date()
var formatter = SimpleDateFormat("dd/MM/YYYY HH:mm:ss.SSSXXX")
var result = formatter.format(now)
println(result)
}
the result expected is ( as it used to be ):
14/03/2026 17:58:51.682+01:00
but i’v got:
14/03/2026 16:58:58.457Z
it seems that the compiler doesn’t know my location… it gives me the time at Greenwich, without the offset for UTC, avoiding the formatting.
This isn’t a matter for the compiler, but for the environment at runtime. Because you don’t specify a time-zone, SimpleDateFormat will use the system one.
You say that this ‘used to’ work — was that more than about six months ago? If so, then I suspect you’re in the UK (or somewhere else at a similar longitude that uses GMT in winter and GMT+1 in summer), in which case the code is doing exactly what it was designed to. If so, you might find that it ‘starts working’ again this time next week, when the clocks go forward!
Note that your example does show a time-zone; that’s the Z suffix. (That stands for ‘Zulu time’, which is the US military term for GMT, and the standard way to indicate no offset. The docs for SimpleDateFormat say: “if the offset value from GMT is 0, "Z" is produced”.)
You can specify a different time-zone by calling SimpleDateFormat.setTimeZone() if needed.
However, Date and its support classes are pretty old and limited; new code is almost always better off using the newer java.time.* classes such as LocalDateTime and DateTimeFormatter.
Thank you for paying attention to my problem. I knew about Zulu. and no… I ran the program in France and the output gave me a result corresponding to the longitude of Greenwich… but after the 5th call. The previous times, the result is correct! I can’t simply model the bug… when I try to isolate it it disappears.
I don’t understand at all. During one call it works and on the next I am entitled to Zulu.
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
fun main() {
val now = ZonedDateTime.now()
val formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss.SSSXXX")
val formattedDate = now.format(formatter)
println(formattedDate)
}
Strange… I can’t think of any reason why that would give a different time-zone when run on the same machine under the same conditions.
(One gotcha worth knowing about java.text.DateFormat etc. is they’re not thread-safe; if you try to reuse the same instance across multiple threads, you risk the results being corrupted. But that doesn’t apply to java.time.format.DateTimeFormatter etc., which are thread-safe. So that doesn’t explain your latest example.)
It’s not clear how the Java runtime determines the system time-zone. I think it varies across platforms, and maybe also across different Java runtimes on the same platform. (For example, this page describes some of the factors for the Oracle JRE running on Windows — though of course Android is likely to differ.)
Different machines can of course be configured with different time-zones — as, presumably, can different containers on the same machine, and probably different users too. And I suspect in some cases it’s affected by your environment variables etc. But if none of that has changed, then I don’t know what to suggest.
One thing I’d try would be to update your POC code to also display the system timezone, as returned by java.util.TimeZone.getDefault().getID(). That may help to narrow down the problem. You could also print out now.zone to confirm it’s using that.
(When debugging, if all else fails, print out everything you can!)
I can’t take it anymore…
I tried to log the Timezone id but it acts like what I thought. here is my very simple now function:
fun now() {
val zone = ZoneId.systemDefault() //.of("Europe/Paris")
val now = ZonedDateTime.now(zone)
Log.e("date", "${now.dayOfMonth}-${now.monthValue}-${now.year} ${now.hour}:${now.minute}:${now.second} -- ${zone.toString()} -- ${java.util.TimeZone.getDefault().getID()}")
}
Well, that has at least narrowed down the problem: the default time-zone seems to vary oddly.
(And that seems most likely to be at the level of the Java runtime or lower, not a problem with Kotlin or Groovy.)
As to why the default time-zone changes, I can’t imagine. But I’ve never written code for Android, so I don’t know what interactions there might be. Do you have any ideas? Could anything be calling TimeZone.setDefault()? Or is the device itself moving or changing time-zone (or language) in between your calls?
And if you know (or can configure) the time-zone you want, it does give you one possible workaround: set that zone on your timestamp. Not ideal, but might get you working in the short term.