java.time
Even though you need to give an old-fashionede Date object to a legacy API beyond your control, I still recommend that you use java.time, the modern Java date and time API, in your own code. The final conversion to Date is pretty straight-forward.
I’d use this formatter for maximum reuse of existing formatters:
private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.appendOffset("+HHmm", "+00")
.toFormatter(Locale.ROOT);
Then we parse and convert like this:
String input = "2021-10-13 11:33:16.000-04";
OffsetDateTime dateTime = OffsetDateTime.parse(input, PARSER);
System.out.println(dateTime);
Instant i = dateTime.toInstant();
Date oldfashionedDate = Date.from(i);
System.out.println(oldfashionedDate);
Output in my time zone, Europe/Copenhagen:
2021-10-13T11:33:16-04:00
Wed Oct 13 17:33:16 CEST 2021
Denmark is at offset +02:00 at this time of year, so 6 hours ahead of the UTC offset -04 from your string. Therefore Date.toString() confusingly prints a clock hour that is 6 hours ahead of the original time of day.
Note: if your forward service accepts anything else than an old-fashioned Date, you should not be using that class. For example, if a String is required, the OffsetDateTime that we got can be formatted into a new string using a second DateTimeFormatter (or in lucky cases, its toString method).
What went wrong in your code?
First, a UTC offset can have positive or negative sign. Instead of -04 you could have had for example +09. Formatters are designed for to take the sign, + or -, as part of the offset. Therefore hardcoding the minus sign as a literal, as in your first attempt, is bound to fail. In your second attempt, yyyy-MM-dd HH:mm:ss.SSSZZ, you are already closer. However, ZZ is for an offset with sign and four digits (like +0530 or -0400; hour and minute), so does not work for a two-digit offset like -04. Your SimpleDateFormat expected more digits where your string ended and therefore threw the exception that you saw.
Link
Oracle tutorial: Date Time explaining how to use java.time.