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.
Related
I have a java.sql.Date object and want to transform it to a java.time.LocalDateTime object.
For comparison, I am able to do a similar transformation using java.util.Date:
java.util.Date utilDate = new java.util.Date(sqlDate.getTime());
System.out.println("date with time: " + utilDate);
This answer doesn't work for me, as my java.sql.Date does not have a getTimestamp method.
For reference, this question addresses the opposite transformation.
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310.
Do not use java.sql.Date
Do not use java.util.Date
Do not use java.sql.Timestamp
Do not use java.util.Calendar
Use only java.time classes.
For exchanging date-time values with a database, use JDBC 4.2 or later.
The java.sql.Date class pretends to represent a date-only value.
If you are handed a java.sql.Date object, immediately convert it to a java.time.LocalDate. Use the new method toLocalDate added to that old class.
LocalDate localDate = myJavaSqlDate.toLocalDate() ;
You asked for a java.time.LocalDateTime object. You have the necessary date portion. Now you need to assign the time-of-day portion.
LocalTime localTime = LocalTime.of( 15 , 30 );
Combine.
LocalDateTime localDateTime = LocalDateTime.of( localDate, localTime ) ;
A LocalDateTime is inherently ambiguous. 3:30 PM 🕞 in Japan 🇯🇵 is a different moment than 3:30 PM 🕞 in Morocco 🇲🇦.
To determine a moment, a specific point on the timeline, place your LocalDateTime within the context of a time zone. You get a ZonedDateTimeObject.
ZoneId zoneId = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zonedDateTime = localDateTime.atZone( zoneId ) ;
To view that moment as seen in UTC, with an offset from UTC of zero hours-minutes-seconds, extract an Instant.
Instant instant = zonedDateTime.toInstant() ;
To answer your question as asked
There’s a wealth of good information in the clever answer by Basil Bourque. Not least the recommendation to avoid the java.sql.Date class completely so you won’t need the conversion.
For this answer I am assuming that you are getting a java.sql.Date from a legacy API that you can’t afford to upgrade to java.time just now. So you do need some conversion, and you have reasons to ask for a LocalDateTime representing the time in the default time zone of the JVM (a fragile practice). There is still a question to consider: do you want only the date part of the Date, or its point in time? Asking because a java.sql.Date was meant for representing a date without time of day, but the API does not enforce this, and a java.sql.Date holds a point in time with millisecond precision. I hope we already told you that this is a confusing class better to be avoided if you can.
To get the start of the day:
java.sql.Date oldfashionedSqlDate
= java.sql.Date.valueOf(LocalDate.of(2021, Month.OCTOBER, 26));
System.out.println("java.sql.Date: " + oldfashionedSqlDate);
LocalDateTime dateTime = oldfashionedSqlDate.toLocalDate().atStartOfDay();
System.out.println("LocalDateTime: " + dateTime);
Output (assuming the default time zone of the JVM has not changed in the meantime):
java.sql.Date: 2021-10-26
LocalDateTime: 2021-10-26T00:00
To get the point in time: To pick up the full precision held in the Date object:
java.sql.Date oldfashionedSqlDate = new java.sql.Date(1_666_000_000_000L);
System.out.println("java.sql.Date: " + oldfashionedSqlDate);
long epochMilli = oldfashionedSqlDate.getTime();
LocalDateTime dateTime = Instant.ofEpochMilli(epochMilli)
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
System.out.println("LocalDateTime: " + dateTime);
Output in my time zone:
java.sql.Date: 2022-10-17
LocalDateTime: 2022-10-17T03:46:40
Since the conversion is time zone dependent, output in other time zones will differ in most cases.
How do I get the current date and time in Java?
I am looking for something that is equivalent to DateTime.Now from C#.
Just construct a new Date object without any arguments; this will assign the current date and time to the new object.
import java.util.Date;
Date d = new Date();
In the words of the Javadocs for the zero-argument constructor:
Allocates a Date object and initializes it so that it represents the time at which it was allocated, measured to the nearest millisecond.
Make sure you're using java.util.Date and not java.sql.Date -- the latter doesn't have a zero-arg constructor, and has somewhat different semantics that are the topic of an entirely different conversation. :)
The Java Date and Calendar classes are considered by many to be poorly designed. You should take a look at Joda Time, a library commonly used in lieu of Java's built-in date libraries.
The equivalent of DateTime.Now in Joda Time is:
DateTime dt = new DateTime();
Update
As noted in the comments, the latest versions of Joda Time have a DateTime.now() method, so:
DateTime dt = DateTime.now();
tl;dr
Instant.now()
java.time
The java.util.Date class has been outmoded by the new java.time package (Tutorial) in Java 8 and later. The old java.util.Date/.Calendar classes are notoriously troublesome, confusing, and flawed. Avoid them.
ZonedDateTime
Get the current moment in java.time.
ZonedDateTime now = ZonedDateTime.now();
A ZonedDateTime encapsulates:
Date.
Time-of-day, with a fraction of a second to nanosecond resolution.
Time zone.
If no time zone is specified, your JVM’s current default time zone is assigned silently. Better to specify your desired/expected time zone than rely implicitly on default.
ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt = ZonedDateTime.now( z );
UTC
Generally better to get in the habit of doing your back-end work (business logic, database, storage, data exchange) all in UTC time zone. The code above relies implicitly on the JVM’s current default time zone.
The Instant class represents a moment in the timeline in UTC with a resolution of nanoseconds.
Instant instant = Instant.now();
The Instant class is a basic building-block class in java.time and may be used often in your code.
When you need more flexibility in formatting, transform into an OffsetDateTime. Specify a ZoneOffset object. For UTC use the handy constant for UTC.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC );
Time Zone
You easily adjust to another time zone for presentation to the user. Use a proper time zone name, never the 3-4 letter codes such as EST or IST.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime nowMontreal = instant.atZone( z );
Generate a String representation of that date-time value, localized.
String output = DateTimeFormatter
.ofLocalizedDate( FormatStyle.FULL )
.withLocale( Locale.CANADA_FRENCH )
.format ( nowMontreal );
Instant
Or, to stay in UTC, use Instant. An Instant object represents a moment on the timeline, to nanosecond resolution, always in UTC. This provides the building block for a zoned date-time, along with a time zone assignment. You can think of it conceptually this way:
ZonedDateTime = Instant + ZoneId
You can extract an Instant from a ZonedDateTime.
Instant instantNow = zdt.toInstant();
You can start with an Instant. No need to specify a time zone here, as Instant is always in UTC.
Instant now = Instant.now();
I prefer using the Calendar object.
Calendar now = GregorianCalendar.getInstance()
I find it much easier to work with. You can also get a Date object from the Calendar.
http://java.sun.com/javase/6/docs/api/java/util/GregorianCalendar.html
In Java 8 it's:
ZonedDateTime dateTime = ZonedDateTime.now();
import java.util.Date;
Date now = new Date();
Note that the Date object is mutable and if you want to do anything sophisticated, use jodatime.
java.lang.System.currentTimeMillis(); will return the datetime since the epoch
import org.joda.time.DateTime;
DateTime now = DateTime.now();
If you create a new Date object, by default it will be set to the current time:
import java.util.Date;
Date now = new Date();
Java has always got inadequate support for the date and time use cases. For example, the existing classes (such as java.util.Date and SimpleDateFormatter) aren’t thread-safe which can lead to concurrency issues. Also there are certain flaws in API. For example, years in java.util.Date start at 1900, months start at 1, and days start at 0—not very intuitive. These issues led to popularity of third-party date and time libraries, such as Joda-Time. To address a new date and time API is designed for Java SE 8.
LocalDateTime timePoint = LocalDateTime.now();
System.out.println(timePoint);
As per doc:
The method now() returns the current date-time using the system
clock and default time-zone, not null. It obtains the current
date-time from the system clock in the default time-zone. This will
query the system clock in the default time-zone to obtain the current
date-time. Using this method will prevent the ability to use an
alternate clock for testing because the clock is hard-coded.
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 ) ;
I try to get the date of yesterday. So I write the next function:
public String getYestrday() {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
return dateFormat.format(date.getDate() - 1);
}
But it gives me the next warning:
The method getDate() from the type Date is deprecated
and it doesn't do it work.
Thank you for your help.
Date#getDate() is a deprecated method after JDK 1.1. You should be using Calendar class instead to manipulate dates.
From API:
Prior to JDK 1.1, the class Date had two additional functions. It
allowed the interpretation of dates as year, month, day, hour, minute,
and second values. It also allowed the formatting and parsing of date
strings. Unfortunately, the API for these functions was not amenable
to internationalization. As of JDK 1.1, the Calendar class should be
used to convert between dates and time fields and the DateFormat class
should be used to format and parse date strings. The corresponding
methods in Date are deprecated.
It is also clearly documented in the API using Date#getDate() to use Calendar#get(Calendar.DATE);
Deprecated. As of JDK version 1.1, replaced by
Calendar.get(Calendar.DAY_OF_MONTH)
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
return dateFormat.format(cal.getTime());
Use java.util.Calendar to do it. Or try JODA.
you can use Calendar class to do the same task:
Calendar c = new Calendar();
//c.add(Calendar.DAY_OF_MONTH, -1);
Date d = c.getTime();
Avoid java.util.Date & .Calendar
The accepted answer is correct. However, the java.util.Date and .Calendar classes are notoriously troublesome. Avoid them. Use either Joda-Time or the new java.time package (in Java 8).
Separate Date-Time Manipulation From Formatting
Also, the code in the question mixes date-time work with formatting. Separate those tasks to make your code clear and testing/debugging easier.
Time Zone
Time zone is critical in date-time work. If you ignore the issue, the JVM's default time zone will be applied. A better practice is to always specify rather than rely on default. Even when you want the default, explicitly call getDefault.
The beginning of the day is defined by the time zone. A new day dawns earlier in Paris than in Montréal. So if by "yesterday" you mean the first moment of that day, then you should (a) specify a time zone, and (b) call withTimeAtStartOfDay.
Joda-Time
Example code in Joda-Time 2.3.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime today = DateTime.now( timeZone );
Or convert from a java.util.Date object.
DateTime today = new DateTime( myJUDate, timeZone );
Subtract a day to get to yesterday (or day before).
DateTime yesterday = today.minusDays( 1 );
DateTime yesterdayStartOfDay = today.minusDays( 1 ).withTimeAtStartOfDay();
By default, Joda-Time and java.time parse/generate strings in ISO 8601 format.
String output = yesterdayStartOfDay.toString(); // Uses ISO 8601 format by default.
Use a formatter for a full date as four digit year, two digit month of year, and two digit day of month (yyyy-MM-dd). Such a formatter is already defined in Joda-Time.
String outputDatePortion = ISODateFormat.date().print( yesterdayStartOfDay );
Following works for me
int date = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
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 ) ;