diff --git a/moshi-adapters/src/main/java/com/squareup/moshi/adapters/Iso8601Utils.kt b/moshi-adapters/src/main/java/com/squareup/moshi/adapters/Iso8601Utils.kt index 7ba3518aa..99df198b7 100644 --- a/moshi-adapters/src/main/java/com/squareup/moshi/adapters/Iso8601Utils.kt +++ b/moshi-adapters/src/main/java/com/squareup/moshi/adapters/Iso8601Utils.kt @@ -125,8 +125,16 @@ internal fun String.parseIsoDate(): Date { // if the value has no time component (and no time zone), we are done val hasT = readChar(this, offset, 'T') if (!hasT && this.length <= offset) { - // Note that this uses the host machine's time zone. That's a bug. - return GregorianCalendar(year, month - 1, day).time + val calendar: Calendar = GregorianCalendar(TIMEZONE_Z, Locale.US) + calendar.isLenient = false + calendar[Calendar.YEAR] = year + calendar[Calendar.MONTH] = month - 1 + calendar[Calendar.DAY_OF_MONTH] = day + calendar[Calendar.HOUR_OF_DAY] = 0 + calendar[Calendar.MINUTE] = 0 + calendar[Calendar.SECOND] = 0 + calendar[Calendar.MILLISECOND] = 0 + return calendar.time } if (hasT) { offset++ diff --git a/moshi-adapters/src/test/java/com/squareup/moshi/adapters/Rfc3339DateJsonAdapterTest.java b/moshi-adapters/src/test/java/com/squareup/moshi/adapters/Rfc3339DateJsonAdapterTest.java index 671382066..603565075 100644 --- a/moshi-adapters/src/test/java/com/squareup/moshi/adapters/Rfc3339DateJsonAdapterTest.java +++ b/moshi-adapters/src/test/java/com/squareup/moshi/adapters/Rfc3339DateJsonAdapterTest.java @@ -95,7 +95,9 @@ public void variableFractionDigits() throws Exception { @Test public void absentTimeZone() throws Exception { - assertThat(adapter.fromJson("\"1970-01-01\"")).isEqualTo(newDateWithHostZone(1970, 1, 1)); + // A date-only string with no time zone is interpreted as midnight UTC. + assertThat(adapter.fromJson("\"1970-01-01\"")).isEqualTo(newDate(1970, 1, 1, 0, 0, 0, 0, 0)); + assertThat(adapter.fromJson("\"2025-11-20\"")).isEqualTo(newDate(2025, 11, 20, 0, 0, 0, 0, 0)); assertThat(adapter.fromJson("\"1970-01-01Z\"")).isEqualTo(newDate(1970, 1, 1, 0, 0, 0, 0, 0)); try { adapter.fromJson("\"1970-01-01T00:00:00.000\""); @@ -112,14 +114,5 @@ private Date newDate( return new Date(calendar.getTimeInMillis() - TimeUnit.MINUTES.toMillis(offset)); } - /** - * Dates specified without any time or timezone (like "1970-01-01") are returned in the host - * computer's time zone. This is a longstanding bug that we're attempting to stay consistent with. - */ - private Date newDateWithHostZone(int year, int month, int day) { - Calendar calendar = new GregorianCalendar(); - calendar.set(year, month - 1, day, 0, 0, 0); - calendar.set(Calendar.MILLISECOND, 0); - return new Date(calendar.getTimeInMillis()); - } } +