Java中获取非UTC时区(Asia/Kolkata)的月份起止时间问题
问题排查与解决方案
问题根源
你的代码核心错误出在时间戳转换步骤:
return Timestamp.valueOf(istDateTime.toLocalDateTime()).getTime();
istDateTime.toLocalDateTime()会剥离时区信息,得到印度时区的本地时间(比如2023-09-01T00:00),但Timestamp.valueOf()方法会将这个LocalDateTime视为JVM默认时区的时间来转换为时间戳。当机器时区是UTC时,它会把2023-09-01T00:00当成UTC时间处理,自然得到错误的时间戳。
修正后的代码
直接将ZonedDateTime转换为Instant(UTC时间戳的标准表示),再获取毫秒级时间戳,完全不受机器时区影响:
import java.time.*; public class MonthTimestampUtil { public static Long getStartTimeStampOfMonth(Month month, Year year) { LocalDate startDate = LocalDate.of(year.getValue(), month, 1); LocalDateTime startDateTime = LocalDateTime.of(startDate, LocalTime.MIN); ZonedDateTime istDateTime = startDateTime.atZone(ZoneId.of("Asia/Kolkata")); // 直接转换为Instant并获取时间戳 return istDateTime.toInstant().toEpochMilli(); } public static Long getEndTimeStampOfMonth(Month month, Year year) { LocalDate startDate = LocalDate.of(year.getValue(), month, 1); LocalDate endDate = startDate.withDayOfMonth(startDate.lengthOfMonth()); LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.MAX); ZonedDateTime istDateTime = endDateTime.atZone(ZoneId.of("Asia/Kolkata")); return istDateTime.toInstant().toEpochMilli(); } }
优化简化方案
使用YearMonth类可以更简洁地处理年月逻辑,避免手动计算月末日期:
import java.time.*; public class MonthTimestampUtil { public static Long getStartTimeStampOfMonth(Month month, Year year) { YearMonth yearMonth = YearMonth.of(year.getValue(), month); // 直接生成印度时区的月初零时ZonedDateTime ZonedDateTime startZoned = yearMonth.atDay(1).atStartOfDay(ZoneId.of("Asia/Kolkata")); return startZoned.toInstant().toEpochMilli(); } public static Long getEndTimeStampOfMonth(Month month, Year year) { YearMonth yearMonth = YearMonth.of(year.getValue(), month); // 获取月末日期并生成印度时区的最后一刻ZonedDateTime ZonedDateTime endZoned = yearMonth.atEndOfMonth().atTime(LocalTime.MAX).atZone(ZoneId.of("Asia/Kolkata")); return endZoned.toInstant().toEpochMilli(); } }
结果验证
- 2023年9月起始时间(Asia/Kolkata 2023-09-01 00:00:00)对应的时间戳为
1693506600000 - 2023年9月结束时间(Asia/Kolkata 2023-09-30 23:59:59.999)对应的时间戳为
1696098599999
完全符合预期,且不受机器时区影响。
内容的提问来源于stack exchange,提问作者Sanjay Prajapat
相关产品推荐
相关产品推荐

