I am trying to instantiate GregorianCalendar with TimeZone GMT, but whenever I call the getTime() method, it gives me time in local TimeZone. Here is my code:
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
System.out.println(cal.getTime());
The output I am getting is this:
Sat Nov 28 19:55:49 PKT 2009
Please help!
I'm not sure if this answers your question, but this is one way to get "now" in GMT.
import java.text.*
import java.util.*
Calendar cal = new GregorianCalendar();
Date date = cal.getTime();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(formatter.format(date));
See the Javadoc on SimpleDateFormat for different patterns. Also, you may want to consider Joda Time as it is far superior for dates and times.
The problem is not with GregorianCalendar but with Date, which is being used to format the date/time for toString for println.
If you want control of date formatting, you'll need to instantiate your own DateFormat - I always use SimpleDateFormat because I'm rather picky about how I want my dates to look.
If you're not interested in the details of how the date is formatted, you can also use one of the getInstance... factory methods of DateFormat.
You can explicitly setTimeZone on a DateFormat (including SimpleDateFormat, of course).
tl;dr
Instant.now().toString()
2020-03-08T00:21:48.647951Z
java.util.Date::toString tells a lie
Your call to GregorianCalendar::getTime returns a java.util.Date. As you can see with this method and class naming, these classes are badly designed.
Then you implicitly called Date::toString to generate text that represents the value within that object. That value is actually in UTC, being merely a count of milliseconds since the epoch reference of first moment of 1970 in UTC. Unfortunately, that method dynamically applies the JVM’s current default time zone while generating the text. This creates the illusion of that zone being contained within the object.
Confusing? Yes. One of many reasons to never use these legacy date-time classes. Use java.time classes instead.
java.time
The other Answers are correct, but now obsolete. The terrible Date, Calendar, GregorianCalendar, and SimpleDateFormat classes were years ago supplanted by the modern java.time classes defined in JSR 310.
To get the current moment in UTC, use Instant. This basic building block class in java.time is always in UTC, by definition.
Instant instant = Instant.now() ;
Generate a string in standard in ISO 8601 format by calling toString.
String output = instant.toString() ;
See this code run live at IdeOne.com.
2020-03-08T00:21:48.647951Z
For more flexible formatting when generating strings, use the OffsetDateTime class. Search Stack Overflow to learn about DateTimeFormatter.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
Related
Calendar calendar1 = Calendar.getInstance();
calendar1.setTime(LeaveDate);
calendar1.add(Calendar.DAY_OF_MONTH, ProcessDate);
Date fullDate1 = calendar1.getTime();
SimpleDateFormat date1 = new SimpleDateFormat("yyyy-MM-dd");
Here the output i.e., date1 is string, how to convert it to Date
tl;dr
Reading your code, apparently you want to take the current moment as seen in the current default time zone, adjust to a particular day of month, and then convert to a moment as seen in UTC to be represented by the outmoded class java.util.Date.
java.util.Date // Legacy class. Replaced by `java.time.Instant`.
.from( // New conversion method added to old class, to move between legacy and modern classes.
ZonedDateTime // Represents a moment as seen in a particular time zone.
.now() // Implicitly applies the JVM’s current default time zone.
.withDayOfMonth( yourDesiredDayOfMonthGoesHere ) // Adjust to another moment on another date. Returns another `ZonedDateTime` object immutably, rather than altering original.
.toInstant() // Adjust from time zone to UTC. Same moment, different wall-clock time.
) // Returns an object for the same moment, but as a legacy `Date` object. Avoid using this class if at all possible.
But your title asks for something different. The title asks how to generate text in a ISO 8601 standard format (YYYY-MM-DD) for a Calendar object. Assuming your Calendar object is a GregorianCalendar object, we can cast. Then we can convert to the modern java.time.ZonedDateTime object, extract the date-only java.time.LocalDate object, and generate standard text. The java.time classes use ISO 8601 formats by default when parsing/generating text, so no need for a formatting pattern.
(GregorianCalendar) yourCalendarHere // Cast from the more general `Calendar` to the more specific `GregorianCalendar`.
.toZonedDateTime() // Convert from legacy class to modern. Same moment in the same time zone. Returns a `java.time.ZonedDateTime` object.
.toLocalDate() // Strip away the time zone and the time-of-day, leaving only the date. Returns a `java.time.LocalDate` object.
.toString() // Generate text representing the value of that date in standard ISO 8601 format, YYYY-MM-DD. Returns a `String` object.
Tip: Stop using the terribly flawed legacy date-time classes. Use only java.time.
Formatters
Here the output i.e., date1 is string, how to convert it to Date
You seem to misunderstand the classes involved.
Your date1 is a variable declared to be a SimpleDateFormat object. That class is a formatter. As a formatter, its job is to generate text, not hold text nor hold a date. So your variable is misnamed, as it does not hold a date.
Avoid legacy classes
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310. Never use Date, Calendar, SimpleDateFormat, and such.
java.time
Replace this:
Calendar calendar1 = Calendar.getInstance();
… with this:
ZonedDateTime zdt = ZonedDateTime.now() ; // Implicitly uses the JVM’s current default time zone.
I assume that in this code:
calendar1.setTime(LeaveDate);
… the LeaveDate (should have been named with initial lowercase, leaveDate) represents a java.util.Date object. And you are trying to get a calendar object set to the moment represented by that Date object.
In java.time, we use immutable objects. So, no use of set methods. In java.time, if handed a java.util.Date object, immediately convert to an Instant. Both classes represent a moment as seen in UTC, with an offset of zero hours-minutes-seconds. To convert, use the new conversion methods added to the old classes.
Instant instant = leaveDate.toInstant() ;
Adjust that moment into a time zone.
ZoneId z = ZoneId.systemDefault() ; // The JVM’s current default time zone.
ZonedDateTime zdt = instant.atZone( z ) ;
Both instant & zdt represent the same moment, the very same point on the timeline. But their date and time-of-day are adjusted for the wall-clock time used by the people of two different regions. If someone in Iceland, where they use UTC as their time zone, called someone in Tokyo, and both people looked up to see the calendar and clock on their respective walls, they would see a different time and possibly a different date.
In your line:
calendar1.add(Calendar.DAY_OF_MONTH, ProcessDate);
… I am guessing that you want to set the day-of-month while keeping the same month, year, and time-of-day. For example, let's use the 23rd. Notice that we generate a new ZonedDateTime rather than alter ("mutate") the original. Adjustments are made automatically if the result would be impossible, such as the 30th of February.
ZonedDateTime zdtForSpecificDayOfMonth = zdt.withDayOfMonth( 23 ) ; // Change day-of-month to the 23rd.
Regarding your line:
Date fullDate1 = calendar1.getTime();
… as I said above, you should avoid using Date in modern Java. But if you must do so to interoperate with old code not yet updated to java.time, extract an Instant from the ZonedDateTime object, and convert to a java.util.Date.
Instant instant = zdtForSpecificDayOfMonth.toInstant() ; // Adjust from a time zone to an offset of zero hours-minutes-seconds.
java.util.Date d = Date.from( instant ) ;
Parsing dates in Java with DateFormat or descendants
Tested with Java's REPL jshell
jshell> import java.text.SimpleDateFormat;
jshell> var df = new SimpleDateFormat("yyyy-MM-dd");
df ==> java.text.SimpleDateFormat#f67a0200
jshell> Date dt = df.parse("2022-02-15");
dt ==> Tue Feb 15 00:00:00 CET 2022
Read the official JavaDoc for class SimpleDateFormat to figure out how to use it to parse a String to Date:
import java.text.SimpleDateFormat;
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date dt = df.parse("2022-02-15");
System.out.println(dt); // prints Tue Feb 15 00:00:00 CET 2022
Explained:
The "yyyy-MM-dd" as argument to the constructor is a date-format literal (representing ISO-date format).
The parse method parses a String with this format and returns the Date object if valid format, or throws a ParseException.
Or search Stackoverflow for [java] String to Date to find similar questions.
Formatting dates in Java with DateFormat or descendants
The other way round you can also format a Date object to have a well-formatted String representation. Use the format method of your DateFormat instance:
import java.text.SimpleDateFormat;
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date dt = df.parse("2022-02-15");
String formatted = df.format(dt);
System.out.println(formatted);
For example to format your Calendar instance use:
Calendar calendar1 = Calendar.getInstance();
// whatever modifies the calendar left out here
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String formatted = df.format(dt);
System.out.println(calendar1.getTime());
I have UTC date and I need to create Date object with exact same value as UTC ( legacy reasons ).
I have managed to do it:
String date = "2012-05-05 12:13:14";
TemporalAccessor formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneId.of("UTC"))
.parse(date);
Instant instant = Instant.from(
formatter
); //
ZonedDateTime zdf = ZonedDateTime.ofInstant(instant,ZoneId.of("UTC"));
Calendar calendar = Calendar.getInstance();
calendar.set(zdf.getYear(),zdf.getMonthValue(),zdf.getDayOfMonth(),zdf.getHour(),zdf.getMinute(),zdf.getSecond());
Date dt = calendar.getTime();
Date d2 = Date.from(instant);
However, what bothers me -
When I create date object, it should display the date in my JVM's default timezone. But here dt has exact same value as my input UTC date, but dt2 has same date represented in my default timezone, why did this happen? Why is one not converted and another is?
Thanks for explaining!
Preserving the hour of day versus preserving the moment
I’ll explain the central lines one by one.
Calendar calendar = Calendar.getInstance();
This creates a Calendar with the same time zone as your JVM’s default time zone. Unlike Date a Calendar has got a time zone.
calendar.set(zdf.getYear(),zdf.getMonthValue(),zdf.getDayOfMonth(),
zdf.getHour(),zdf.getMinute(),zdf.getSecond());
This sets your Calendar to the same wall clock time as your ZonedDateTime, namely 12:13:14. Since the ZonedDateTime and the Calendar have different time zones (UTC and your local time zone, respectively), this results in a different moment.
Also #VGR is correct: While the date of the ZonedDateTIme was in May (month 5), you are setting the Calendar month to June because Calendar months are confusingly 0-based, from 0 for January through 11 for December.
Date d2 = Date.from(instant);
This is the correct conversion from Instant to Date and gives you the same point in time, the same moment as the Instant. And therefore not the same moment as the Calendar and dt.
And it was probably understood in your question, but for anyone reading along I would like to state directly: Date and Calendar are poorly designed and long outdated. You should not use them except when necessary for interacting with a legacy API that you cannot change or don’t want to upgrade just now. For all other uses stick to java.time, the modern Java date and time API.
Links
All about java.util.Date on Jon Skeet’s code blog
Stack Overflow question: Why is January month 0 in Java Calendar?
tl;dr
As others said, a java.util.Date represents a moment in UTC. Its toString method lies to you by dynamically applying the JVM’s current default time zone while generating is poorly-formatted string. One of many reasons to never use this class.
Do not waste you time on trying to understand the terrible classes Date & Calendar. They are now legacy, to be avoided.
Use only java.time classes for all your date-time handling.
Details
The Answer by Ole V.V. is correct and should be accepted. I'll add a few thoughts.
You are mixing the terrible legacy date-time classes (Date, Calendar) with their modern replacements (Instant, ZonedDateTime). Do not mix these. The legacy classes are entirely supplanted by the java.time classes with the adoption of JSR 310.
There is no need to ever use Date or Calendar again. Do not waste your time trying to understand them. They were replaced for a reason – many reasons, actually. Use your brains and time for more productive work.
If you must use the legacy classes to interoperate with old code not yet updated to java.time, convert to-and-fro by calling the new to…/from… conversion methods added to the old classes. Perform your business logic, data exchange, and data storage all using the java.time classes.
The java.util.Date class is replaced by Instant.
java.util.Date d = Date.from( instant ) ; // From modern to legacy.
Instant instant = d.toInstant() ; // From legacy to modern.
The Calendar class, or rather its commonly used subclass GregorianCalendar, is replaced by ZonedDateTime. Assuming your Calendar object is really a GregorianCalendar underneath, you can cast, then convert.
Calendar c = GregorianCalendar.from( zonedDateTime ) ; // From modern to legacy.
ZonedDateTime zonedDateTime = ( (GregorianCalendar) c ).toZonedDateTime() ; // From legacy to modern.
Here is a chart mapping the legacy classes to the modern ones.
I am currrently working with Java JODATIME DateTime. I have a dateTime as 2015-09-08T11:00:00.000Z , When I convert to date using toDate().
I am getting the date object as Tue Sep 08 06:00:00 CDT 2015.
DateTime dateTime = 2015-09-08T11:00:00.000Z; // Not a string I am getting this date from another API.
Date date = dateTime.toDate(); //Tue Sep 08 06:00:00 CDT 2015.
May I know what is the thing happening here?
A Date object simply holds the number of milliseconds since 1 Jan 1970 UTC. It does not contain presentation logic, so your comment that it equates to 6am CDT shows that something (your IDE, or some date formatter) has applied a timezone in order to render the date to a human readable form. The code is actually working correctly.
Apparently you are calling the toString method on the java.util.Date object. That class’ implementation of toString has the confusing feature of silently applying your JVM’s current default time zone to the date-time value as it generates a String representation.
The java.util.Date object itself has no time zone, and is always in UTC.
This is one of many reasonable avoid these old java.util.Date/.Calendar classes. Use java.time, now built into Java 8 and later. For older versions of Java, use Joda-Time.
Also this topic has been addressed many many times before on StackOverflow. Please search before posting.
A quick bit of example code in java.time. An Instant is a moment on the timeline in UTC. Your input string happens to be in standard ISO 8601 format which java.time uses by default when parsing/generating strings. So you can parse directly without bothering to specify a parsing pattern.
String input = "2015-09-08T11:00:00.000Z";
Instant instant = Instant.parse( input );
Adjust that Instant into a specific time zone to get a ZonedDateTime.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Search StackOverflow.com for many more examples of java.time.
Actually there is a time zone buried in the source code of java.util.Date but is ignored for practical purposes.
I am trying to parse a String into Date.
I am using
new SimpleDateFormat("yyyyMMdd-HH:mm:ss.SSS").parse("20140923-14:32:34.456")
My output is: (Date object)
Tue Sep 23 14:32:34 EDT 2014
I dont understand why I do not get the milliseconds. I need the date along with milliseconds and not just the milliseconds.
Expected Output: (Date object)
Tue Sep 23 14:32:34.456 EDT 2014
thanks
PS: I dont want a string object in the end but a Date.
You're just printing out the result of calling Date.toString() which happens not to include the milliseconds. If you print out the result of calling getTime() on the date, you'll see that it ends in "456", showing that it has parsed the milliseconds.
Also, don't be fooled by the "EDT" part of the output of Date.toString(). It doesn't mean that this is a Date object "in" EDT... a Date doesn't have a time zone at all; it's just a number of milliseconds since the unix epoch.
I'd advise you to explicitly set the time zone of your SimpleDateFormat, however - even if you deliberately set it to the system default time zone. By doing it explicitly, you make it clear to the reader that you meant to use that time zone, rather than just that you failed to think about it. You should take the same approach to the locale, too - in this case I'd probably specify Locale.US, which is usually a good bet for formats which are designed more for machine-parsing than humans.
You need to use the format when printing the date you just read too:
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HH:mm:ss.SSS")
Date date = sdf.parse("20140923-14:32:34.456");
System.out.println(date); // Tue Sep 23 14:32:34 EDT 2014
System.out.println(sdf.format(date)); // 20140923-14:32:34.456
Your Date object does already contain the correct milliseconds. It's just that, when you are writing the Date object back out again, the default String representation of a Date does not include milliseconds.
You presumably have:
DateFormat myFormat = new SimpleDateFormat("yyyyMMdd-HH:mm:ss.SSS");
Date myDate = myFormat.parse("20140923-14:32:34.456");
To output the date with milliseconds, you should use:
System.out.println(myFormat.format(myDate));
Instead of reusing myFormat, you could use a different DateFormat that also includes milliseconds in its specification.
The answer by Jon Skeet is correct.
Joda-Time
I will add some example code using the Joda-Time library.
The java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat classes bundled with Java are notoriously troublesome, flawed in both design and implementation. Avoid them. Use either Joda-Time or the java.time package in Java 8 (inspired by Joda-Time, defined by JSR 310).
In both Joda-Time and java.time, a date-time object knows its own assigned time zone, unlike in java.util.Date. Another difference is that both those good libraries use immutable objects where we instantiate fresh objects based on original object rather than alter ("mutate") the original.
DateTimeZone timeZone = DateTimeZone.UTC; // Or DateTimeZone.forID( "America/Montreal" )
DateTimeFormatter formatter = DateTimeFormat.forPattern( "yyyyMMdd-HH:mm:ss.SSS" ).withZone( timeZone );
DateTime dateTime = formatter.parseDateTime("20140923-14:32:34.456"); // Parsed *and* assigned the specified time zone.
String output = dateTime.toString();
You can convert to another time zone.
DateTime dateTimeKolkata = dateTime.withZone( DateTimeZone.forID( "Asia/Kolkata" ) );
If you really need a java.util.Date, perhaps required by other classes, convert from Joda-Time.
java.util.Date date = dateTime.toDate();
I am trying to instantiate GregorianCalendar with TimeZone GMT, but whenever I call the getTime() method, it gives me time in local TimeZone. Here is my code:
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
System.out.println(cal.getTime());
The output I am getting is this:
Sat Nov 28 19:55:49 PKT 2009
Please help!
I'm not sure if this answers your question, but this is one way to get "now" in GMT.
import java.text.*
import java.util.*
Calendar cal = new GregorianCalendar();
Date date = cal.getTime();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(formatter.format(date));
See the Javadoc on SimpleDateFormat for different patterns. Also, you may want to consider Joda Time as it is far superior for dates and times.
The problem is not with GregorianCalendar but with Date, which is being used to format the date/time for toString for println.
If you want control of date formatting, you'll need to instantiate your own DateFormat - I always use SimpleDateFormat because I'm rather picky about how I want my dates to look.
If you're not interested in the details of how the date is formatted, you can also use one of the getInstance... factory methods of DateFormat.
You can explicitly setTimeZone on a DateFormat (including SimpleDateFormat, of course).
tl;dr
Instant.now().toString()
2020-03-08T00:21:48.647951Z
java.util.Date::toString tells a lie
Your call to GregorianCalendar::getTime returns a java.util.Date. As you can see with this method and class naming, these classes are badly designed.
Then you implicitly called Date::toString to generate text that represents the value within that object. That value is actually in UTC, being merely a count of milliseconds since the epoch reference of first moment of 1970 in UTC. Unfortunately, that method dynamically applies the JVM’s current default time zone while generating the text. This creates the illusion of that zone being contained within the object.
Confusing? Yes. One of many reasons to never use these legacy date-time classes. Use java.time classes instead.
java.time
The other Answers are correct, but now obsolete. The terrible Date, Calendar, GregorianCalendar, and SimpleDateFormat classes were years ago supplanted by the modern java.time classes defined in JSR 310.
To get the current moment in UTC, use Instant. This basic building block class in java.time is always in UTC, by definition.
Instant instant = Instant.now() ;
Generate a string in standard in ISO 8601 format by calling toString.
String output = instant.toString() ;
See this code run live at IdeOne.com.
2020-03-08T00:21:48.647951Z
For more flexible formatting when generating strings, use the OffsetDateTime class. Search Stack Overflow to learn about DateTimeFormatter.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;