So, I started to test around a bit with the Java-GregorianCalendar Class and noted a weird behaviour occuring, when initializing the Object with milliseconds. What bothered me was, although I set the milliseconds to 0 the time showed 1 o'clock.
After browsing StackOverflow a bit I noticed that Java sometimes gets confused with summer and winter time. So my question is, if although the time change was already done this year and we live in winter time again, this weird behaviour comes from winter and summertime.
Here is the Code I was testing around with:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class TestCalendar {
public static void main(String[] args) {
GregorianCalendar c = new GregorianCalendar();
c.setTimeInMillis(-3600000);
System.out.println(c.getTimeInMillis());
System.out.println(c.get(Calendar.HOUR));
String format = "mm:ss";
if (c.get(Calendar.HOUR_OF_DAY) > 0) format = "HH:mm:ss";
System.out.println(new SimpleDateFormat(format).format(c.getTime()));
}
}
This gave me the Output
-3600000
0
0
The best thing would be to find a solution which is independent from substracting -3600000 as if on other computers this "bug" does not exist I dont want to have 23:00:00 :)
EDIT:
After trying a bit more out and thanks to the Feedback I was able to fix my little problem by just adding this line just after initializing the Calendar:
c.setTimeZone(TimeZone.getTimeZone("GMT"));
tl;dr
Problem: You are mistakenly changing the date, not just the time-of-day. On top of that, a time zone is implicitly being applied.
Solution: Instead use the modern java.time classes.
LocalDate
.now() // Better to explicitly pass the desired/expected time zone as a `ZoneId` object.
.atStartOfDay() // Again, better to explicitly pass the desired/expected time zone as a `ZoneId` object.
Returns a LocalDateTime (BEWARE: Not a moment, not a point on the timeline).
2018-11-01T00:00
Much better to specify time zone.
LocalDate
.now(
ZoneId.of( "Pacific/Auckland" )
)
.atStartOfDay(
ZoneId.of( "Pacific/Auckland" )
)
Returns a ZonedDateTime. This is a moment, is a point on the timeline.
2018-11-02T00:00+13:00[Pacific/Auckland]
GregorianCalendar::setTimeInMillis is not setting time-of-day
Apparently you mistakenly thought the GregorianCalendar::setTimeInMillis would set the time-of-day without affecting the date. Among the many flaws in these legacy date-time classes is some very poor choices in naming classes and methods.
But, no, that method redefines the moment as a count of milliseconds since epoch reference date of 1970-01-01T00:00Z.
Add in the time zone implicitly assigned to GregorianCalendar, and you have unexpected results.
I started to test around a bit with the Java-GregorianCalendar
Don’t.
Those old date-time classes bundled with the earliest versions of Java are terrible. They were supplanted years ago by the java.time classes defined in JSR 310.
Specifically, to track a moment in UTC, use Instant.
initializing the Object with milliseconds
Don’t.
Tracking time as a count-from-epoch-reference is prone to error. There are many different epoch reference dates in use in the industry. There are different granularities in use in the industry (whole seconds, milliseconds, microseconds, nanoseconds).
So a count-from-epoch is ambiguous. Also prone to confusing and missed errors because humans cannot read the meaning of the values.
When exchanging date-time values, use strings in standard ISO 8601 format instead.
When handed a count of milliseconds from the Unix epoch of first moment of 1970 in UTC, parse as an Instant.
Instant instant = Instant.ofEpochMilli( … ) ;
java.time
The modern solution uses java.time classes instead.
Get your date.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
ZonedDateTime
Apparently you want the first moment of the day. By the way, do not think of this as “midnight” as that term is ambiguous.
The first moment of the day may not be 00:00. Anomalies such as Daylight Saving Time (DST) mean that the first moment on some dates in some zones may be another time such as 01:00. Let java.time determine the first moment.
Specify a time zone.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = localDate.atStartOfDay( z ) ;
If you want to see that same moment in UTC, extract a Instant.
Instant instant = zdt.toInstant() ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Setting c.setTimeInMillis(0); sets the time to January 1, 1970 at 00:00:00 GMT (1970-01-01 00:00:00 GMT) which is called the epoch
https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#setTimeInMillis(long)
public void setTimeInMillis(long millis)
Sets this Calendar's current time from the given long value.
Parameters:
millis - the new time in UTC milliseconds from the epoch.
See Also:
setTime(Date), getTimeInMillis()
If you want to set the time to midnight, I think you want to do.
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
Related
I'm writing automated bdds for a rest API. And the API returns a date. I want to get the difference between the returned date from the API and the current date today.
So for example, the API returns "March 13, 2018 12:00 pm"
And today's date is "March 11, 2018 12:00pm"
The times are always the same, it's only the days that change. And the API will also return a date that's in the future.
I have this piece of code:
Date currentDate = Date.from(Instant.now());
// endDate comes from the API
long diff = endDate.getTime() - currentDate.getTime();
long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
This returns 1, but I want it to include the last day. I can just add +1 at the end of endDate.getTime() - currentDate.getTime(); but I'm not sure if that's the right approach.
I also read that this is not a good solution in general, because it doesn't account for daylight savings time. I'm not sure how or if it would affect my automated bdds when daylight savings comes. What's the best way to capture the difference in days?
Think of it as how many days do I have left until expiration
Your real problem is that your backend REST service is poorly designed.
ISO 8601
First of all, date-time values exchanged should be in standard ISO 8601 format, not some localized presentation string.
The standard formats are used by default in the java.time classes when parsing/generating text.
java.time
Never use the terrible Date class. That class, along with Calendar, SimpleDateFormat, and such, was supplanted years ago by the java.time classes defined in JSR 310.
Date.from(Instant.now())
Never mix the terrible legacy date-time classes (Date) with their replacements (Instant), the modern java.time classes. Mixing these is unnecessary and confusing.
The java.time classes entirely replace their predecessors.
The times are always the same, it's only the days that change. And the API will also return a date that's in the future.
If you only want to exchange date values, without a time-of-day and without a time zone or offset, use LocalDate class, and exchange the ISO 8601 format YYYY-MM-DD such as 2018-03-11. Call LocalDate.parse and LocalDate::toString.
long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
Representing a count of days as a count of milliseconds without the context of a time zone or offset-from-UTC is reckless. Days are not always 24 hours long. They can be 23, 23.5, 25, or some other number of hours.
If you mean to use UTC so as to always have 24-hour days, say so. Represent your date-time with an indication of time zone or offset. For example, the standard format: 2018-03-11T00:00Z where the Z on the end means UTC and is pronounced “Zulu”.
So your entire problem could be reduced to this one-liner.
ChronoUnit.DAYS.between(
LocalDate.now( ZoneId.of( "America/Montreal" ) ) , // Get the current date as seen in the wall-clock time used by the people of a particular region (a time zone).
LocalDate.parse( "2019-01-23" ) // Parse a string in standard ISO 8601 format for a date-only value.
) // Returns a `long` integer number of days elapsed.
Unzoned
If you are not in a position to clean up all those messy design problems, then let's forge ahead, trying to use this messy data.
First fix the am/pm which should be in uppercase.
String input = "March 13, 2018 12:00 pm".replace( " am" , " AM" ).replace( " pm" , " PM" );
Define a formatting pattern to match your input string.
Specify a Locale to determine the human language and cultural norms to use in translating the text.
Locale locale = Locale.US;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MMMM d, uuuu HH:mm a" );
Parse as a LocalDateTime because your input lacks an indicator of time zone or offset-from-UTC.
LocalDateTime ldt = LocalDateTime.parse( input , f );
ldt.toString(): 2018-03-13T12:00
A LocalDateTime purposely has no concept of time zone or offset-from-UTC. So this class cannot represent a moment, is not a point on the timeline.
If you want generic 24-hour days without regard to the reality of anomalies in wall-clock time used by various people in various places, such as Daylight Saving Time (DST), we can continue to use this class.
Get the current date as seen in the wall-clock time used the people to whom your app is aimed (a time zone).
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Get noon on that date, in no particular time zone.
LocalDateTime ldtTodayNoon = LocalDateTime.of( today , LocalTime.NOON ) ;
Count days elapsed.
long daysElapsed =
ChronoUnit.DAYS.between(
ldtTodayNoon ,
ldt
)
;
Of course we could just as well have done this using only LocalDate rather than LocalDateTime, but I followed your problem statement as written.
Notice that in your given example, the string represents a date in the past. So our number of days will be negative.
Zoned
If you did want to account for anomalies seen on some dates in some zones, then you should have represented a moment properly, as discussed above, with an indicator of time zone or offset-from-UTC.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
ZonedDateTime zdtNow = ZonedDateTime.now( z ) ;
Or perhaps you want noon today in the desired time zone. If noon is not a valid time-of-day on this date in this zone, the ZonedDateTime class will adjust. Be sure to read the ZonedDateTime.of JavaDoc to understand the algorithm of that adjustment.
LocalDate today = LocalDate.now( z ) ;
ZonedDateTime zdtTodayNoon = ZonedDateTime.of( today , LocalTime.NOON , z ) ;
Calculate elapsed time either based in fractional seconds, or in whole calendar days.
Duration d = Duration.between( zdtTodayNoon , zdt ) ; // For a calculation based in whole seconds plus a fractional second in nanoseconds without regard for a calendar, just using generic 24-hour days.
Period p = Period.between( zdtTodayNoon , zdt ) ; // For a calculation based in whole days, for a number of years-months-days based on calendar dates.
If you insist on tracking by a count of milliseconds, call Duration::toMillis.
long millisecondsElapsed = d.toMillis() ; // Entire duration as a total number of milliseconds, ignoring any microseconds or nanos.
All of this has been covered many times already on Stack Overflow. You can learn more and see more examples by searching for these java.time class names.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Hello I am trying to get the current date at java at a Class I created but everything fails. I've seen in many sites
e.g. http://www.mkyong.com/java/java-date-and-calendar-examples/
that the date constructor has no arguments
e.g. Date date = new Date();
Now in my project I try to use it like this and I get the error
that The constructor Date() is undefined
How is this possible? I give you the full code so far
import java.sql.Date;
import java.text.SimpleDateFormat;
public class Utility {
String title;
int ID;
Date date;
Utility(String t,int ID){
this.ID=ID+1;
title=t;
SimpleDateFormat sdf = new SimpleDateFormat("dd/M/yyyy");
Date a=new Date();// I get the error here
String date = sdf.format(a);
System.out.print(date);
}
}
I work at Eclipse IDE. Can you help me?
The examples you found are for java.util.Date while you are using java.sql.Date
java.sql.Date
has two constructors
Date(long date): Constructs a Date object using the given milliseconds time value.
Date(int year, int month, int day): which is deprecated
and no default Date() constructor.
java.util.Date
among others has a default constructor without arguments
Date(): Allocates a Date object and initializes it so that it represents the time at which it was allocated, measured to the nearest millisecond.
When importing classes, Eclipse will help you fining possible candidates but always check if the first suggestion is really what you want.
You are using the wrong Date class.
Have a look at your imports. Don't use java.sql.Date use java.util.Date instead.
You are importing java.sql.Date use java.util.Date
You have imported wrong class. It is java.util.Date and not java.sql.Date
You can also use use java.util.Calendar as follows:
Calendar c = Calendar.getInstance();
java.util.Date date = c.getTime();
tl;dr
Get today’s date:
LocalDate.now()
Generate text representing today’s date, in your desired format:
LocalDate
.now()
.format(
DateTimeFormatter.ofPattern( "d/M/uuuu" )
)
23/1/2019
Details
The answer by Matteo is correct. You are abusing the java.sql.Date class by treating it as java.util.Date.
But the answers suggesting using java.util.Calendar questions are misguided. Both java.util.Date & Calendar are notoriously bad classes, with poor design and implementation. They are outmoded by the modern java.time.* JSR 310 classes.
Also, when working with date-time you should always think about time zone. Otherwise you'll be getting default time zone with possibly varying behavior at runtime.
java.time
ZonedDateTime zonedDateTime = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
If you want a date-only value, without a time-of-day and without a time zone, use LocalDate.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the code becomes ambiguous to read in that we do not know for certain if you intended to use the default or if you, like so many programmers, were unaware of the issue.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety. Ditto for Year & YearMonth.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I am having trouble understanding java.sql.timestamp.
If I run the java deprecated constructors:
java.sql.Timestamp(106,2,26,1,0,0,0)
java.sql.Timestamp(106,2,26,2,0,0,0)
java.sql.Timestamp(106,2,26,3,0,0,0) //<-- Separated by one hour
I get:
2006-03-26 01:00:00.0
2006-03-26 03:00:00.0
2006-03-26 03:00:00.0 //<--These last two are the same
Daylight savings occurs (at least in my country) around these times. But the dates before and after the time are not moved. Why are two separate hours returning the same time?
I would like to get the timestamp just as my input, How can I force this?
Don't use this deprecated constructor, which is deprecated precisely because it uses the default time zone.
Use a Calendar (or a DateFormat) with the appropriate time zone (CET), set the fields of the calendar (or parse a string containing the date you want to insert), get the milliseconds from the calendar/date, and construct a Timestamp from the milliseconds.
Using System.currentTimeMillis(); gives you Greenwich Mean Time which is unaffected by daylight savings, leap seconds and other surprise adjustments to the date.
long now = System.currentTimeMillis();
Or Specify the timezone manually:
long ms = Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTimeInMillis();
Source: Get GMT Time in Java
tl;dr
The Daylight Saving Time (DST) cut-over means the 2 AM hour never existed. So you are giving invalid inputs.
The ZonedDateTime class tries to help by adjusting your time-of-day input, jumping to 3 AM just as the clock jumped an hour than morning when striking 02:00.
ZonedDateTime
.of( 2006 , 3 , 26 , 2 , 0 , 0 , 0 , ZoneId.of( "Africa/Tunis" ) )
.toString()
2006-03-26T03:00+02:00[Africa/Tunis]
Avoid legacy date-time classes
java.sql.Timestamp is a terrible class, along with its sibling classes such as java.util.Date and Calendar/GregorianCalendar. Among its many design problems is is messy handling of time zones.
Instead, use only the modern java.time classes.
java.time
For moments (a date, a time-of-day, and a time zone or offset-from-UTC), use one of these classes:
Instant — a moment always in UTC.
OffsetDateTime — a moment with an offset-from-UTC (a number of hours-minutes-seconds) but an unknown time zone
ZonedDateTime — a moment with an assigned time zone.
It sounds like you were intending to use a date-time in your own zone.
ZoneId
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the code becomes ambiguous to read in that we do not know for certain if you intended to use the default or if you, like so many programmers, were unaware of the issue.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
ZonedDateTime
Specify a time and a date as seen in the wall-clock time used by the people of a particular region (a time zone).
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt_1 = ZonedDateTime.of( 2006, 3 , 26 , 1 , 0 , 0 , 0 , z ) ;
ZonedDateTime zdt_2 = ZonedDateTime.of( 2006, 3 , 26 , 2 , 0 , 0 , 0 , z ) ;
ZonedDateTime zdt_3 = ZonedDateTime.of( 2006, 3 , 26 , 3 , 0 , 0 , 0 , z ) ;
System.out.println("zdt_1.toString(): " + zdt_1);
System.out.println("zdt_2.toString(): " + zdt_2);
System.out.println("zdt_3.toString(): " + zdt_3);
zdt_1.toString(): 2006-03-26T01:00+01:00[Africa/Tunis]
zdt_2.toString(): 2006-03-26T03:00+02:00[Africa/Tunis]
zdt_3.toString(): 2006-03-26T03:00+02:00[Africa/Tunis]
Daylight Saving Time (DST)
We see a surprise on the third item, where we ask for 2 AM but get 3 AM back. This is understandable, because of a Daylight Saving Time (DST) cut-over or “Spring ahead”. Starting in 2005, Tunisia adopted DST. Later in 2009 they came to their senses and returned to standard time only.
The 2 AM hour does not exist
So there is no 2 AM on that date in Tunisia. When the clock struck 2 AM, it jumped to 3 AM. The 2 AM hour never existed. That day is only 23-hours long rather than the usual 24 hours long. So our code above asked for an invalid date-time. The ZonedDateTime class, rather than throw an Exception, tries to help us out by adjusting to a valid time-of-day. The JavaDoc for ZonedDateTime.of spells this out:
Obtains an instance of ZonedDateTime from a year, month, day, hour, minute, second, nanosecond and time-zone.
This creates a zoned date-time matching the local date-time of the seven specified fields as closely as possible. Time-zone rules, such as daylight savings, mean that not every local date-time is valid for the specified zone, thus the local date-time may be adjusted.
The local date-time is resolved to a single instant on the time-line. This is achieved by finding a valid offset from UTC/Greenwich for the local date-time as defined by the rules of the zone ID.
In most cases, there is only one valid offset for a local date-time. In the case of an overlap, when clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".
In the case of a gap, when clocks jump forward, there is no valid offset. Instead, the local date-time is adjusted to be later by the length of the gap. For a typical one hour daylight savings change, the local date-time will be moved one hour later into the offset typically corresponding to "summer".
So the behavior is a feature, not a bug.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
somebody please tell me how to get the time from the TimeZone class. When I run this code
System.out.println("Default Timezone: " + TimeZone.getDefault())
I got this
Default Timezone: sun.util.calendar.ZoneInfo[id="Asia/Manila",offset=28800000,dstSavings=0,useDaylight=false,transitions=10,lastRule=null]
I can't find any function that will get the time such as TimeZone.getDefault().getTime(). Please help.
Try below to get the time for EST TimeZone:
TimeZone est = TimeZone.getTimeZone("America/New_York");
Calendar calendar = new GregorianCalendar(est);
System.out.println(calendar.getTime()); //<-prints the date
System.out.println(calendar.getTimeInMillis()); //<-prints the time in milliseconds
You can change timezone to other timezones e.g. PST to get the time in other timezones:
TimeZone pst = TimeZone.getTimeZone("America/Los_Angeles");
calendar.setTimeZone(pst);
System.out.println(calendar.getTime()); //<-prints the date
System.out.println(calendar.getTimeInMillis()); //<-prints the time in milliseconds
Hope this helps.
Date theCurrentDateAndTime = new GregorianCalendar(timeZone).getTime();
TimeZone is a abstract class which represent timezone not time. As you mentioned you are invoking the getDefault(),TimeZone.getDefault() by using getDefault() you will get the timezone based on where the program is running.
If you want to just print the date, then you have options like Calendar or Date
or if you wish to move with timezone specific time then set the timezone and get the time of that zone.
Your program will print the date in this way(this is not only the way):
TimeZone defaultTimezone = TimeZone.getDefault();
Calendar calendar = new GregorianCalendar(defaultTimezone);
System.out.println(calendar.getTime());
The TimeZone class represents a time zone not the time. You will have to use either the Date or the Calendar class instead for the time.
You need to use either Date (or) Calendar API to get today date/time.
These APIs use default time zone configured in your system.
You don't.
Javadoc for TimeZone. You'll note this has nothing to do with the current time.
See Calendar
tl;dr
LocalTime.now( // Capture the current time-of-day for a particular time zone. Result discards the zone, leaving an object unaware of any zone or offset.
ZoneId.of( "Asia/Manila" ) // Represent the time zone, the history of past, present, and future changes in offset for a specific region.
)
23:45
java.time
The modern approach to date-time handling uses the java.time classes that supplanted the troublesome old legacy date-time classes.
Your Question is unclear? Are you asking for the current time-of-day for a particular time zone? Or are you asking for information about a time zone itself, its offset from UTC?
Zones
An offset-from-UTC is a number of hours, minutes, and seconds displaced from the same moment UTC. A time zone is a history of the past, present, and future changes in offset used by the people of a particular region.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Asia/Manila" ) ;
Current time-of-day
For only the current time-of-day as seen on the wall-clocks by the people of a particular region, use LocalTime.now and pass the desired zone. The resulting object lacks any concept of zone or offset as the passed zone is discarded after determining the current moment.
LocalTime lt = LocalTime.now( z ) ;
23:45
For the date and time-of-day in that zone, use ZonedDateTime.
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
To capture the current moment in UTC, use Instant.
Instant instant = Instant.now( z ) ;
Time zone info
The ZoneId and ZoneOffset classes supplant TimeZone.
ZoneRules rules = z.getRules() ;
You can interrogate a ZoneId about the rules it uses to define the behavior a particular time zone. You must pass a moment (a Instant), as the entire point of a time zone is that the offset used by the people of that region has changed over history. For example, countries silly enough to practice Daylight Saving Time (DST) change their offset twice a year.
ZoneOffset offset = rules.getOffset( zdt.toInstant() ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I am wanting to adjust 3 Gregorian Calendar dates in Java, with one to be 24 hours before, the other 48, hours before and last 78 hours before. I had been using Calendar.HOUR and changed this to Calendar.HOUR_OF_DAY.
Since I did this my code stopped working. I am comparing the adjusted dates with their original values using a method that uses date1.before(date2) and date1.after(date2) to get a comparisonflag
which can be 1 or 0 which I then use in my code.
I was wondering how to do the adjust the HOUR_OF_DAY in my dates to then achieve
the above.
Some code would have been nice. But if I understand the problem correctly:
From the javadoc of Calendar:
HOUR is used for the 12-hour clock. E.g., at 10:04:15.250 PM the HOUR is 10.
HOUR_OF_DAY is used for the 24-hour clock. E.g., at 10:04:15.250 PM the HOUR_OF_DAY is 22.
When adding/substracting hours from a date:
Calendar cal = Calendar.getInstance();
cal.add(Calendar.HOUR, -24);
cal.add(Calendar.HOUR_OF_DAY, -24);
This should have the same effect.
tl;dr
ZonedDateTime.now() // Capture the current moment as seen through the lens of wall-clock time used by the people of a certain region, a time zone. Better to pass the expected/desired time zone as an optional argument.
.minusHours( 24 ) // Do the math, get earlier moment.
Do not use Calendar
The troublesome Calendar class and related date-time classes bundled with the earliest versions of Java are now legacy, supplanted by the java.time classes.
java.time
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
Use that time zone when asking for the current moment to be captured as a ZonedDateTime object.
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Subtract your target number of hours.
ZonedDateTime zdtMinus24h = zdt.minusHours( 24 ) ;
ZonedDateTime zdtMinus48h = zdt.minusHours( 48 ) ;
ZonedDateTime zdtMinus72h = zdt.minusHours( 72 ) ;
Compare with isBefore, isAfter, and isEqual methods. Also, Comparable is implemented.
Alternatively, you can represent the number-of-hours-to-add as a Duration.
Duration d = Duration.ofHours( 24 ) ;
ZonedDateTime zdtEarlier = zdt.minus( d ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.