java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Also, quoted below is a notice from the home page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Solution using java.time, the modern Date-Time API:
The modern Date-Time API has many types which truly represent a date or time or date-time in a specific timezone. You can choose from the following options as per your specific requirement:
- If you are looking for a type that represents a date without a timezone, you can use LocalDate.now. The good news is that its variant,LocalDate#now(ZoneId)returns the current date from the system clock in the specified time-zone.
- If you are looking for an object that represents a date without a timezone, and with time units set to zero, you can call LocalDate#atStartOfDayon the object obtained with Option#1.
- If you are looking for an Instantrepresenting the Date-Time object obtained with Option#2, you can attach this object withZoneId.of("Etc/UTC")usingLocalDateTime#atZoneto obtain aZonedDateTimeand convert the same into anInstantusingZonedDateTime#toInstant.
Demo:
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
    public static void main(String[] args) {
        LocalDate todayInSystemTz = LocalDate.now();
        System.out.println(todayInSystemTz);
        LocalDate todayInIndia = LocalDate.now(ZoneId.of("Asia/Kolkata"));
        System.out.println(todayInIndia);
        LocalDateTime todayInSystemTzWithZeroTimeUnits = todayInSystemTz.atStartOfDay();
        System.out.println(todayInSystemTzWithZeroTimeUnits);
        ZonedDateTime todayInUtcWithZeroTimeUnits = todayInSystemTzWithZeroTimeUnits.atZone(ZoneId.of("Etc/UTC"));
        System.out.println(todayInUtcWithZeroTimeUnits);
        Instant instant = todayInUtcWithZeroTimeUnits.toInstant();
        System.out.println(instant);
        // Can I represent the obtained Instant in India?
        System.out.println(instant.atZone(ZoneId.of("Asia/Kolkata")));
        // Can I represent the obtained Instant in New York?
        System.out.println(instant.atZone(ZoneId.of("America/New_York")));
    }
}
Output:
2021-06-20
2021-06-20
2021-06-20T00:00
2021-06-20T00:00Z[Etc/UTC]
2021-06-20T00:00:00Z
2021-06-20T05:30+05:30[Asia/Kolkata]
2021-06-19T20:00-04:00[America/New_York]
ONLINE DEMO
The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).
For any reason, if you need to convert this object of Instant to an object of java.util.Date**, you can do so as follows:
Date date = Date.from(instant);
Learn more about the modern Date-Time API from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
**
A java.util.Date object simply represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone e.g.
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String strDateNewYork = sdf.format(date);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = sdf.format(date);