Java 8中如何将UTC时间戳转指定时区?结果不符求助
Hey there! Let's break down why your current code isn't giving the expected result and fix it properly.
The Core Issue
Your original code has a critical misunderstanding: when you use Timestamp.valueOf("2031-04-25 18:30:00"), this method parses the time string using your JVM's default timezone, not UTC. That means the Timestamp you're creating doesn't actually represent UTC 18:30—it represents whatever your local timezone's 18:30 translates to as an Instant. No wonder the conversion to Asia/Calcutta isn't giving you 2031-04-26 00:00!
Correct Solution Using Java 8's java.time API
Java 8's modern date-time API (JSR-310) is designed to avoid these timezone ambiguities. Here's how to properly convert your UTC time to Asia/Calcutta:
import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; public class TimezoneConversion { public static void main(String[] args) { // Step 1: Parse the UTC time string into a LocalDateTime DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime utcLocalTime = LocalDateTime.parse("2031-04-25 18:30:00", formatter); // Step 2: Bind the LocalDateTime to UTC timezone to get a ZonedDateTime ZonedDateTime utcZonedTime = utcLocalTime.atZone(ZoneId.of("UTC")); // Step 3: Convert to Asia/Calcutta timezone (keeping the same instant in time) ZonedDateTime calcuttaTime = utcZonedTime.withZoneSameInstant(ZoneId.of("Asia/Calcutta")); // Output: 2031-04-26T00:00+05:30[Asia/Calcutta] System.out.println(calcuttaTime); } }
If You Need to Use Timestamp (For Legacy Code)
If you must work with Timestamp for compatibility reasons, make sure you create it from a UTC-based Instant:
import java.sql.Timestamp; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; public class TimestampConversion { public static void main(String[] args) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime utcLocalTime = LocalDateTime.parse("2031-04-25 18:30:00", formatter); // Create an Instant representing the UTC time Instant utcInstant = utcLocalTime.atZone(ZoneId.of("UTC")).toInstant(); // Convert to Timestamp (legacy API) Timestamp rawDateTime = Timestamp.from(utcInstant); // Now convert to Asia/Calcutta timezone correctly ZonedDateTime calcuttaTime = ZonedDateTime.ofInstant(rawDateTime.toInstant(), ZoneId.of("Asia/Calcutta")); // Output: 2031-04-26T00:00+05:30[Asia/Calcutta] System.out.println(calcuttaTime); } }
Why Your Original Code Failed
Let's quickly recap the issues with your initial attempts:
ZonedDateTime.ofInstant(Instant.ofEpochMilli(rawDateTime.getTime()), zoneId): SincerawDateTimewas created using your default timezone (not UTC), the Instant here doesn't represent UTC 18:30—so the conversion is based on the wrong point in time.ZonedDateTime.of(rawDateTime.toLocalDateTime(), zoneId): This takes the raw date-time values (18:30) and treats them as if they're already in Asia/Calcutta timezone, completely ignoring that the original time was UTC.
Pro Tip
Stick with Java 8's java.time classes (LocalDateTime, ZonedDateTime, Instant, etc.) whenever possible. They're far more intuitive and less error-prone than the old Timestamp/Date APIs, especially when dealing with timezones.
内容的提问来源于stack exchange,提问作者Tansheet Izhad

