0

Given these two date Strings, I am trying to create a menu that allows you to select from the two dates (these are returned from an API with the users timezone):

2019-12-20T00:00:00.000-05:00 2019-12-19T00:00:00.000-05:00

I use the following code to parse the date string in the users preferred timezone (I have downloaded this locally to their devices). I have verified that the TZUtils.getUsersTimeZone() returns this timezone: America/New York which has an offset of -5.

fun getDateForString(date: String): Date {
        val parser = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
        parser.timeZone = TZUtils.getUsersTimeZone()
        return parser.parse(date)
    }

When these dates are parsed, they are parsed into my local time time (offset -6) and not in the users local time zone (-5), even though I specify to use the users local time zone. When I create the popup menu, I used the following code to show the dates

public String getStringForDate(Date date) {
    DateFormat dateFormat = SimpleDateFormat.getDateInstance(DateFormat.SHORT);
    return dateFormat.format(date);
}

And this returns me the wrong dates to select from (the dates are based on my timezone and not the users). Furthermore, when I select the data from the menu, the function I use to filter data based on if it is the same day as the selected date doesn't work because it uses my timezone as well. How do I fix this or do I just "assume" this will work for users since their devices are in their timezones?

Citut
  • 847
  • 2
  • 10
  • 25
  • I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use `OffsetDateTime` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jan 09 '20 at 22:06

2 Answers2

3

You can use the modern java.time package instead and specially ZonedDateTime that handles time zones.

String str = "2019-12-20T00:00:00.000-05:00";
ZonedDateTime zonedDateTime = ZonedDateTime.parse(str);

And when showing it in the UI use DateTimeFormatter to convert it to a formatted string

DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME; 

or with some custom format

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

which will give you for the 2 formats

System.out.println(formatter.format(zonedDateTime));

2019-12-20T00:00-05:00
2019-12-20 00:00

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
  • Good answer, thanks. `OffsetDateTime` is an even better fit than `ZonedDateTime` since the strings contain an offset (`-05:00`) and no time zone (like America/New_York, for example). For a display equal to the one in the question use `DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)`. – Ole V.V. Jan 09 '20 at 22:09
  • And maybe most importantly: For use with Android below API level 26, to use java.time add [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to the Android project and make sure to import the date and time classes from `org.threeten.bp` with subpackages. – Ole V.V. Jan 09 '20 at 22:12
0

SimpleDateFormat.getDateInstance(...) will give you an instance in the JVM's default time zone.

Set the time zone to whatever you need it to be.

DateFormat dateFormat = SimpleDateFormat.getDateInstance(DateFormat.SHORT);
dateFormat.setTimeZone(/* whatever */);
return dateFormat.format(date);
Andy Turner
  • 137,514
  • 11
  • 162
  • 243