Stick to ZonedDateTime
To preserve the time zone simply preserve your ZonedDateTime. It can be formatted directly to the output your require. Don’t involve the outdated and poorly designed Date class.
private static final String API_TIME_STAMP_PATTERN = "yyyy-MM-dd_HH:mm:ss.SSS";
private static final DateTimeFormatter FORMATTER
        = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz y", Locale.ROOT);
public static void printDate(ZonedDateTime datetime) {
    System.out.println("---> " + datetime.format(DateTimeFormatter.ofPattern(API_TIME_STAMP_PATTERN)));
    System.out.println(datetime.format(FORMATTER));
    System.out.println("\n");
}
Try it out:
    ZonedDateTime zdt = ZonedDateTime.of(
            2019, 3, 13, 8, 46, 26, 593_000_000, ZoneId.of("Etc/UTC"));
    printDate(zdt);
Output:
---> 2019-03-13_08:46:26.593
Wed Mar 13 08:46:26 UTC 2019
Your conversion is not changing the time zone
A Date falsely pretends to have a time zone. It hasn’t got any. So there is no change of time zone going on. toInstant() discards the time zone because an Instant hasn’t got a time zone either. Date.from() performs the conversion withut any regard to time zone. System.out.println() implicitly calls Date.toString(). The toString() method uses the JVM’s default time zone for rendering the string. It’s pretty confusing alright.