SimpleDateFormat vs ZonedDateTime with timezone - java

I'm trying to convert PST timestamp to epoch time.
The first method I tried is using zoned datetime by passing America/Los Angeles as input time zone.
public static void changeStringDateFormatToEpoch(String oldDate, String format) throws ParseException {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format);
LocalDateTime dt = LocalDateTime.parse(oldDate, dtf);
ZonedDateTime zdtzone = dt.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println("When date: "+ oldDate + " is in format "+ format + " --> " + zdtzone.toEpochSecond());
}
After this I tried running the below code which uses SimpleDateFormat to do the same
public static void changeStringDateFormatToEpochSimpleDate(String oldDate, String format) throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date dt = sdf.parse(oldDate);
long epoch = dt. getTime();
System.out.println("When date: "+ oldDate + " is in format "+ format + " --> " + epoch);
}
How is that both the outputs are similar, when in the 2nd case I'm not even specifying the timezone of the input date.
Shouldn't the epoch time get affected since the input time zone is PST(America/Los Angeles)?
sample input
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
class Scratch {
public static void main(String[] args) {
String date = "2019-11-27 04:32:41.000-0800"; //yyyy-MM-dd HH:mm:ss.SSSZ
String date2 = "2019-11-27 04:32:41"; // yyyy-MM-dd HH:mm:ss
try {
changeStringDateFormatToEpoch(date, "yyyy-MM-dd HH:mm:ss.SSSZ");
changeStringDateFormatToEpoch(date2, "yyyy-MM-dd HH:mm:ss");
changeStringDateFormatToEpochSimpleDate(date, "yyyy-MM-dd HH:mm:ss.SSSZ");
changeStringDateFormatToEpochSimpleDate(date2, "yyyy-MM-dd HH:mm:ss");
} catch (ParseException e) {
e.printStackTrace();
}
}
public static void changeStringDateFormatToEpoch(String oldDate, String format) throws ParseException {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format);
LocalDateTime dt = LocalDateTime.parse(oldDate, dtf);
ZonedDateTime zdtzone = dt.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println("When date: "+ oldDate + " is in format "+ format + " --> " + zdtzone.toEpochSecond());
}
public static void changeStringDateFormatToEpochSimpleDate(String oldDate, String format) throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date dt = sdf.parse(oldDate);
long epoch = dt. getTime();
System.out.println("SimpleDate : When date: "+ oldDate + " is in format "+ format + " --> " + epoch);
}
}
output
When date: 2019-11-27 04:32:41.000-0800 is in format yyyy-MM-dd HH:mm:ss.SSSZ --> 1574857961
When date: 2019-11-27 04:32:41 is in format yyyy-MM-dd HH:mm:ss --> 1574857961
SimpleDate : When date: 2019-11-27 04:32:41.000-0800 is in format yyyy-MM-dd HH:mm:ss.SSSZ --> 1574857961000
SimpleDate : When date: 2019-11-27 04:32:41 is in format yyyy-MM-dd HH:mm:ss --> 1574857961000

Your SimpleDateFormat-based code works as expected only because you are running it on machine in the Pacific time zone. SimpleDateFormat instances are initialized with the system default time zone, but it can be changed.
To make your code robust and portable, use the first approach. Parse a LocalDateTime, and then combine it with an explicit ZoneId, rather than inferring the default time zone.
Some of the date times parsed in your example use an offset date-time. This is helpful; many developers in zones afflicted by daylight-saving time overlook the need to include some indication whether daylight saving is currently in effect when storing local time stamps. Without it, there is ambiguity in parsing times during the autumn transition to standard time.
In any case, you should be aware that it is also possible to combine a LocalDateTime with a ZoneOffset to produce an OffsetDateTime, and from that, an epoch time.

After editing your changeStringDateFormatToEpoch() has a new problem: it is now ignoring the offset -0800 given in the string. As long as it happens to agree with the time zone you provide hardcoded in the code, the result is OK; but if the offset had been different, you would have obtained an incorrect result. Even for America/Los_Angeles time zone you will get an incorrect result at the overlap when summer time (DST) ends, clock times are repeated and the offset is your only chance of distinguishing.
The code using SimpleDateFormat can be said to have the opposite problem: in case of an absent time zone or offset it uses the JVM’s default time zone, which may or may not be the intended. Chances are further harmed by the fact that the JVM time zone setting can be changed at any time by another part of your program or another program running in the same JVM.
If you know that America/Los Angeles time zone will be intended for strings without zone or offset, the solution is this variant:
/** #throws DateTimeParseException if oldDate is not in the format given */
public static void changeStringDateFormatToEpoch(String oldDate, String format) {
// Time zone to use if neither time zone nor UTC offset is given in the string
ZoneId defaultZone = ZoneId.of("America/Los_Angeles");
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format).withZone(defaultZone);
ZonedDateTime zdt = ZonedDateTime.parse(oldDate, dtf);
System.out.println("When date: " + oldDate + " is in format " + format
+ " --> " + zdt.toEpochSecond());
}
Let’s try it out using your own code:
String date = "2019-11-27 04:32:41.000-0800"; //yyyy-MM-dd HH:mm:ss.SSSZ
String date2 = "2019-11-27 04:32:41"; // yyyy-MM-dd HH:mm:ss
changeStringDateFormatToEpoch(date, "yyyy-MM-dd HH:mm:ss.SSSZ");
changeStringDateFormatToEpoch(date2, "yyyy-MM-dd HH:mm:ss");
Even when running in my time zone, Europe/Copenhagen, the results agree:
When date: 2019-11-27 04:32:41.000-0800 is in format yyyy-MM-dd HH:mm:ss.SSSZ --> 1574857961
When date: 2019-11-27 04:32:41 is in format yyyy-MM-dd HH:mm:ss --> 1574857961
To answer your questions
How is that both the outputs are similar, when in the 2nd case I'm not
even specifying the timezone of the input date.
In the second case SimpleDateFormat uses the time zone setting of your JVM. Only because this is America/Los_Angeles (or another time zone that uses offset -08:00 on November 27) do the outputs agree. When running in a different time zone they would not.
Shouldn't the epoch time get affected since the input time zone is
PST(America/Los Angeles)?
The output is affected by the JVM’s default time zone. It doesn’t use UTC or some other default unless the default is set so.
Do not use SimpleDateFormat
The SimpleDateFormat class is notoriously troublesome and long outdated. It’s somehow not surprising that it gives you a surprising result. Do use java.time, the modern Java date and time API that ZonedDateTime is a part of for your date and time work. It tends to give a lot fewer surprises and more natural code.

ZonedDateTime zonedDateTime = LocalDateTime.now().atZone(ZoneId.of("Asia/Hong_Kong"));
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy - hh:mm:ss zzz");
String formattedString = zonedDateTime.format(dateTimeFormatter);
System.out.println(String.format("ZonedDateTime [%s], Formatted ZonedDateTime [%s]", zonedDateTime, formattedString));
output is - ZonedDateTime [2022-03-17T17:09:27.471+08:00[Asia/Hong_Kong]], Formatted ZonedDateTime [03/17/2022 - 05:09:27 HKT]
but when i do
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/mm/yyyy - hh:mm:ss zzz");
String format = simpleDateFormat.format(zonedDateTime);
System.out.println(format);
throw error
Cannot format given Object as a Date
Which means SimpleDateFormat is not support ZonedDateTime ?

Related

DateTimeParseException: Text '2020-04-01T08:53:47.000+02:00 00:00' could not be parsed, unparsed text found at index 29

Getting a DateTimeParseExcpetion when trying to convert the String 2020-04-01T08:53:47.000+02:00 00:00
String date = "2020-04-01T08:53:47.000+02:00 00:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSz");
parsedDate = LocalDateTime.parse(date,formatter).toString();
System.out.println(parsedDate);
Your pattern is not the same as your String. Check the last part where is 000+02:00 00:00.
Your pattern is: SSSz
If you try this:
String date = "2020-04-01T08:53:47.000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
It will works because your date is like your pattern. Note that every number in the date is into pattern too.
But for your date there is an empty space what no make sense, so removing it, the code works perfectly.
String date = "2020-04-01T08:53:47.000+02:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSz");
Output:
2020-04-01T08:53:47
Note that z is the local time and means "zero hour offset" or "Zulu time" (UTC) and you can use Locale.
The 00:00 at the end of your date-time string doesn't make sense to me. Parse the date-time string after stripping that.
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDate = "2020-04-01T08:53:47.000+02:00 00:00";
strDate = strDate.substring(0, strDate.lastIndexOf(' '));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSz", Locale.ENGLISH);
LocalDateTime parsedDate = LocalDateTime.parse(strDate, formatter);
System.out.println(parsedDate);
OffsetDateTime odt = OffsetDateTime.parse(strDate);
System.out.println(odt);
System.out.println(odt.getOffset());
}
}
Output:
2020-04-01T08:53:47
2020-04-01T08:53:47+02:00
+02:00
Note: You can parse your date-time string (after striping 00:00 from the end of it) to OffsetDateTime in order to preserve the zone-offset information.
Use the built-in formatter
The built-in DateTimeFormatter.ISO_OFFSET_DATE_TIME matches the part of your string that we can understand. And it can parse just that part and ignore the rest.
String date = "2020-04-01T08:53:47.000+02:00 00:00";
ParsePosition pp = new ParsePosition(0);
OffsetDateTime odt = OffsetDateTime.from(
DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(date, pp));
System.out.println("Date and time: " + odt);
System.out.println("Unparsed text: " + date.substring(pp.getIndex()));
Output:
Date and time: 2020-04-01T08:53:47+02:00
Unparsed text: 00:00
Since your string contains an offset from UTC, OffsetDateTime is the correct class to parse into. If we used LocalDateTIme, the offset would be ignored, and we would end up not knowing at which offset the time was to be interpreted, that is, we could not know which point in time it was. With OffsetDateTime the point in time is unambiguous. If you want to convert to the time in your own time zone, convert to ZonedDateTime (still not LocalDateTime).
ZonedDateTime timeInMyTimeZone = odt.atZoneSameInstant(ZoneId.systemDefault());
System.out.println("Date and time: " + timeInMyTimeZone);
Example output:
Date and time: 2020-04-01T11:53:47+05:00[Asia/Aqtobe]
Links
Documentation links:
DateTimeFormatter.ISO_OFFSET_DATE_TIME.
The two-arg DateTimeFormatter.parse​(CharSequence, ParsePosition) that I used.

Java date with the format : YYYYMMDDHHMMss.000Z as GMT

I need to get today’s date at midnight in my time zone in the format YYYYMMDDHHMMss.000Z as date and time in GMT.
I'm interested in the date, not the time of day.
In my system when I have got a date: 20201001220000.000Z it is a day 20201003 as summertime for GMT. I am asking this question because I need to compare the 20201001220000.000Z with today’s date.
I need to get the date ( TODAY midnight) in format yyyyMMddHHmmss.SSSZ. TODAY midnight 20201004 in my system is: 20201003220000.000Z this date will be compared with other dates e.g 20201002220000.000Z. The problem is that I can't get midnight.
java.time
Edit:
I tend to understand that you want to format today’s date into your format for comparison with other date-time strings in UTC (GMT) in the same format. For comparing dates and times I suggest that you compare date-time objects, not strings. So the options are two:
Parse the existing string, convert it to a date in your time zone and compare it to today’s date.
Parse your existing string into a point in time. Compare to the start of today’s date.
Let’s see both options in code.
1. Convert to date and compare dates:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SSSX");
ZoneId zone = ZoneId.systemDefault();
LocalDate today = LocalDate.now(zone);
String gmtString = "20201001220000.000Z";
LocalDate dateFromGmtString = formatter.parse(gmtString, Instant::from)
.atZone(zone)
.toLocalDate();
if (dateFromGmtString.isAfter(today)) {
System.out.println(gmtString + " is in the future");
} else if (dateFromGmtString.isBefore(today)) {
System.out.println(gmtString + " was on a past date");
} else {
System.out.println(gmtString + " is today");
}
Output:
20201001220000.000Z was on a past date
2. Find start of today’s date and compare times
Instant startOfDay = LocalDate.now(zone).atStartOfDay(zone).toInstant();
String gmtString = "20201001220000.000Z";
Instant timeFromGmtString = formatter.parse(gmtString, Instant::from);
if (timeFromGmtString.isBefore(startOfDay)) {
System.out.println(gmtString + " was on a past date");
} else {
System.out.println(gmtString + " is today or later");
}
20201001220000.000Z was on a past date
Original answer
You may be after the following. I recommend that you use java.time, the modern Java date and time API, for your date and time work.
DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SSSX");
String gmtString = "20201001220000.000Z";
Instant instant = sourceFormatter.parse(gmtString, Instant::from);
LocalDate date = instant.atZone(ZoneId.systemDefault()).toLocalDate();
String dayString = date.format(DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(dayString);
When I run the code in Europe/Warsaw time zone, the output is:
20201002
So the date has been converted from October 1 GMT to October 2 in Poland.
Edit:
… How can I get midnight?
To get the start of the day (usually 00:00):
ZonedDateTime startOfDay = time.atZone(ZoneId.systemDefault())
.truncatedTo(ChronoUnit.DAYS);
System.out.println(startOfDay);
2020-10-02T00:00+02:00[Europe/Warsaw]
Link: Oracle tutorial: Date Time explaining how to use java.time.
Try this.
String format = "yyyy-MM-dd HH:mm:ss.SSS O";
ZonedDateTime zdt = ZonedDateTime.now().withZoneSameInstant(ZoneId.of("GMT"));
System.out.println(zdt.format(DateTimeFormatter.ofPattern(format)));
Prints a US East coast time as
2020-10-03 14:47:18.809 GMT
You can delete the spaces, dashes and colons as desired. But do not use Date or related formatters as they are outdated. Use the classes from the java.time package.
You can do it as follows:
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// Today
LocalDate today = LocalDate.now();
// Midnight in the JVM's default time-zone
ZonedDateTime zdt = today.atStartOfDay(ZoneId.systemDefault());
// Printing zdt in its default format i.e. value returned by zdt.toString()
System.out.println(zdt);
// Printing zdt in your custom format
DateTimeFormatter customFormat = DateTimeFormatter.ofPattern("yyyyMMddHHmmss.SSSZ");
String dateTimeStrCustom = zdt.format(customFormat);
System.out.println(dateTimeStrCustom);
}
}
Output:
2020-10-04T00:00+01:00[Europe/London]
20201004000000.000+0100

Get 1 year back dateTime from current dateTime in yyyy-MM-dd HH:mm:ss.SSS format

I need to get the datetime of 1 year back considering the current datetime. The format needed to be in "yyyy-MM-dd HH:mm:ss.SSS"
ex : 2019-08-13 12:00:14.326
I tried following. But getting an error.
LocalDate now = LocalDate.now();
LocalDate localDate = LocalDate.parse(now.toString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")).minusYears(1);
Below Exception returned:
DateTimeParseException: Text '2020-08-13' could not be parsed
What's the best way to do this in Java 8+ ?
A LocalDate does not hold any information about hours, minutes, seconds or any unit below, instead, it holds information about year, month and day. By calling LocalDate.now() you are getting the date of today (the day of code execution).
If you need the time as well, use a LocalDateTime, which has a method now(), too, and actually consists of a LocalDate and a LocalTime.
Your error message tells you that the content of a LocalDate cannot be formatted using the given pattern (-String) "yyyy-MM-dd HH:mm:ss.SSS" because that pattern requires values for hours (HH), minutes (mm), seconds (ss) and milliseconds (SSS are fraction of seconds and three of them make it be milliseconds).
For parsing Strings or formatting datetimes, a LocalDateTime may be suitable but if you want to reliably add or subtract a year or any other amount of time, you'd rather use a class that considers time zones, offsets and daylight saving like ZonedDateTime or OffsetDateTime...
The LocalDate is the wrong class for your requirement as it does not hold the time information. You can use LocalDateTime but I suggest you use OffsetDateTime or ZonedDateTime so that you can get the flexibility of using the Zone Offset and Zone ID. Check https://docs.oracle.com/javase/tutorial/datetime/iso/overview.html for an overview of date-time classes.
Also, keep in mind that a date or time or date-time object is an object that just holds the information about date/time; it doesn't hold any information about formatting and therefore no matter what you do when you print their objects, you will always get the output what their toString() methods return. In order to format these classes or in other words, to get a string representing a custom format of these objects, you have formatting API (e.g. the modern DateTimeFormatter or legacy SimpleDateFormat) at your disposal.
A sample code:
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// Get the current date & time at UTC
OffsetDateTime odtNow = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println("Now at UTC: " + odtNow);
// Get the date & time one year ago from now at UTC
OffsetDateTime odtOneYearAgo = odtNow.minusYears(1);
System.out.println("One year ago at UTC: " + odtNow);
// Define a formatter for the output in the desired pattern
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
// Format the date & time using your defined formatter
String formattedDateTimeOneYearAgo = formatter.format(odtOneYearAgo);
System.out.println("Date Time in the pattern, yyyy-MM-dd HH:mm:ss.SSS: " + formattedDateTimeOneYearAgo);
}
}
Output:
Now at UTC: 2020-08-13T08:50:36.277895Z
One year ago at UTC: 2020-08-13T08:50:36.277895Z
Date Time in the pattern, yyyy-MM-dd HH:mm:ss.SSS: 2019-08-13 08:50:36.277
May not be the best way, but this will do it
LocalDateTime date = LocalDateTime.now().minusYears(1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println(date.format(formatter));
You say you want date+time from 1 year back, but you give it only a date (LocalDate). If you just want the date, all you need to do is:
LocalDate now = LocalDate.now();
LocalDate then = now.minusYears(1);
And if you want the timestamp also, then:
LocalDateTime now = LocalDateTime.now();
LocalDateTime then = now.minusYears(1);
And so on for other objects.
As mentioned you should use LocalDateTime instead of LocalDate.
Your exception was thrown because your input String is in ISO_DATE_TIME format
Java Doc
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
String now = dateTimeFormatter.format(LocalDateTime.now());
LocalDateTime localDate = LocalDateTime.parse(now, dateTimeFormatter);

use pattern with #JsonFormat for java.time.Instant. Do not want to manually write code for it and use annotations [duplicate]

I'm trying to format an Instant to a String using the new Java 8 Date and Time API and the following pattern:
Instant instant = ...;
String out = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(instant);
Using the code above I get an exception which complains about an unsupported field:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra
at java.time.Instant.getLong(Instant.java:608)
at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
...
Time Zone
To format an Instant a time-zone is required. Without a time-zone, the formatter does not know how to convert the instant to human date-time fields, and therefore throws an exception.
The time-zone can be added directly to the formatter using withZone().
DateTimeFormatter formatter =
DateTimeFormatter.ofLocalizedDateTime( FormatStyle.SHORT )
.withLocale( Locale.UK )
.withZone( ZoneId.systemDefault() );
If you specifically want an ISO-8601 format with no explicit time-zone
(as the OP asked), with the time-zone implicitly UTC, you need
DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.from(ZoneOffset.UTC))
Generating String
Now use that formatter to generate the String representation of your Instant.
Instant instant = Instant.now();
String output = formatter.format( instant );
Dump to console.
System.out.println("formatter: " + formatter + " with zone: " + formatter.getZone() + " and Locale: " + formatter.getLocale() );
System.out.println("instant: " + instant );
System.out.println("output: " + output );
When run.
formatter: Localized(SHORT,SHORT) with zone: US/Pacific and Locale: en_GB
instant: 2015-06-02T21:34:33.616Z
output: 02/06/15 14:34
public static void main(String[] args) {
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneId.systemDefault());
System.out.println(DATE_TIME_FORMATTER.format(new Date().toInstant()));
}
DateTimeFormatter.ISO_INSTANT.format(Instant.now())
This saves you from having to convert to UTC. However, some other language's time frameworks may not support the milliseconds so you should do
DateTimeFormatter.ISO_INSTANT.format(Instant.now().truncatedTo(ChronoUnit.SECONDS))
The Instant class doesn't contain Zone information, it only stores timestamp in milliseconds from UNIX epoch, i.e. 1 Jan 1070 from UTC.
So, formatter can't print a date because date always printed for concrete time zone.
You should set time zone to formatter and all will be fine, like this :
Instant instant = Instant.ofEpochMilli(92554380000L);
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.UK).withZone(ZoneOffset.UTC);
assert formatter.format(instant).equals("07/12/72 05:33");
assert instant.toString().equals("1972-12-07T05:33:00Z");
Instants are already in UTC and already have a default date format of yyyy-MM-dd. If you're happy with that and don't want to mess with time zones or formatting, you could also toString() it:
Instant instant = Instant.now();
instant.toString()
output: 2020-02-06T18:01:55.648475Z
Don't want the T and Z? (Z indicates this date is UTC. Z stands for "Zulu" aka "Zero hour offset" aka UTC):
instant.toString().replaceAll("[TZ]", " ")
output: 2020-02-06 18:01:55.663763
Want milliseconds instead of nanoseconds? (So you can plop it into a sql query):
instant.truncatedTo(ChronoUnit.MILLIS).toString().replaceAll("[TZ]", " ")
output: 2020-02-06 18:01:55.664
etc.
Or if you still want to use formatter created from pattern
you can just use LocalDateTime instead of Instant:
LocalDateTime datetime = LocalDateTime.now();
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(datetime)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
String text = date.toString(formatter);
LocalDate date = LocalDate.parse(text, formatter);
I believe this might help, you may need to use some sort of localdate variation instead of instant

Java get UTC time

I want to get the time in UTC time zone. So I wrote the code:
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;
public class RegularSandbox {
public static void main(String[] args) {
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println("DATETIME = " + Date.from(utc.toInstant()));
}
}
The problem is the output shows me the time in PST (my local timezone). I need it to output the time in UTC so I can store it inside of my databases.
System.out.println("DATETIME = " + utc.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
You do too much when trying to convert to old java.util.Date. And then you implicitly use its method toString() which should be well known for the observed behaviour to print the instant always in your system timezone.
But printing in UTC timezone is extremely simple, not even a formatter is needed if you can cope with ISO-8601-notation:
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println("DATETIME = " + utc.toInstant());
// output: DATETIME = 2015-12-30T15:01:18.483Z (Instant is always printed with UTC offset)
System.out.println("DATETIME = " + utc);
// output: DATETIME = 2015-12-30T15:01:57.611Z (the same because you
// have explicitly set the UTC Offset when constructing the ZonedDateTime)
You see, the behaviour of toString() of the new Java-8 classes Instant and ZonedDateTime is much clearer and is always in ISO-format. No need for a confusing conversion to Date.
About specialized formatters, you will only need one if you intend to deviate from ISO-8601-format - maybe using localized month names or extra printing of weekdays etc. Example in US-style:
System.out.println(
"DATETIME = "
+ utc.format(DateTimeFormatter.ofPattern("MM/dd/uuuu h:mm:ss a xxx")));
// output: DATETIME = 12/30/2015 3:14:50 PM +00:00
Note that the answer of #LowLevel uses a wrong pattern. If you leave out the symbol a (AM/PM-marker) then you should not choose the half-day-hour-symbol h but H (24-hour-format). And the timezone or offset symbol (here x) is crucial because otherwise the printed datetime will not be automatically recognized as being in UTC timezone.
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
final SimpleDateFormat sdf = new SimpleDateFormat("EEE, MMM d, yyyy hh:mm:ss a z"); // you can specify format that you want to get
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC time: " + sdf.format(utc));
private Calendar getUTCTime(){
Calendar calendar = Calendar.getInstance();
// Assuming your time is in utc + 8
calendar.add(Calendar.HOUR, -8);
return calendar;
}
I suggest you to use Joda-Time.
DateTime dt = new DateTime(DateTimeZone.UTC);

Categories

Resources