I created a Date object in Java. When I do so, it shows something like: date=Tue Aug 09 00:00:00 IST 2011. As a result, it appears that my Excel file is lesser by one day (27 feb becomes 26 feb and so on) I think it must be because of time. How can I set it to something like 5:30 pm?
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY,17);
cal.set(Calendar.MINUTE,30);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MILLISECOND,0);
Date d = cal.getTime();
Also See
Joda time
Calendar doc
Can you show code which you use for setting date object? Anyway< you can use this code for intialisation of date:
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse("2011-01-01 00:00:00")
I should like to contribute the modern answer. This involves using java.time, the modern Java date and time API, and not the old Date nor Calendar except where there’s no way to avoid it.
Your issue is very likely really a timezone issue. When it is Tue Aug 09 00:00:00 IST 2011, in time zones west of IST midnight has not yet been reached. It is still Aug 8. If for example your API for putting the date into Excel expects UTC, the date will be the day before the one you intended. I believe the real and good solution is to produce a date-time of 00:00 UTC (or whatever time zone or offset is expected and used at the other end).
LocalDate yourDate = LocalDate.of(2018, Month.FEBRUARY, 27);
ZonedDateTime utcDateDime = yourDate.atStartOfDay(ZoneOffset.UTC);
System.out.println(utcDateDime);
This prints
2018-02-27T00:00Z
Z means UTC (think of it as offset zero from UTC or Zulu time zone). Better still, of course, if you could pass the LocalDate from the first code line to Excel. It doesn’t include time-of-day, so there is no confusion possible. On the other hand, if you need an old-fashioned Date object for that, convert just before handing the Date on:
Date oldfashionedDate = Date.from(utcDateDime.toInstant());
System.out.println(oldfashionedDate);
On my computer this prints
Tue Feb 27 01:00:00 CET 2018
Don’t be fooled, it is correct. My time zone (Central European Time) is at offset +01:00 from UTC in February (standard time), so 01:00:00 here is equal to 00:00:00 UTC. It’s just Date.toString() grabbing the JVMs time zone and using it for producing the string.
How can I set it to something like 5:30 pm?
To answer your direct question directly, if you have a ZonedDateTime, OffsetDateTime or LocalDateTime, in all of these cases the following will accomplish what you asked for:
yourDateTime = yourDateTime.with(LocalTime.of(17, 30));
If yourDateTime was a LocalDateTime of 2018-02-27T00:00, it will now be 2018-02-27T17:30. Similarly for the other types, only they include offset and time zone too as appropriate.
If you only had a date, as in the first snippet above, you can also add time-of-day information to it:
LocalDate yourDate = LocalDate.of(2018, Month.FEBRUARY, 27);
LocalDateTime dateTime = yourDate.atTime(LocalTime.of(17, 30));
For most purposes you should prefer to add the time-of-day in a specific time zone, though, for example
ZonedDateTime dateTime = yourDate.atTime(LocalTime.of(17, 30))
.atZone(ZoneId.of("Asia/Kolkata"));
This yields 2018-02-27T17:30+05:30[Asia/Kolkata].
Date and Calendar vs java.time
The Date class that you use as well as Calendar and SimpleDateFormat used in the other answers are long outdated, and SimpleDateFormat in particular has proven troublesome. In all cases the modern Java date and time API is so much nicer to work with. Which is why I wanted to provide this answer to an old question that is still being visited.
Link: Oracle Tutorial Date Time, explaining how to use java.time.
If you don't have access to java 8 and the API java.time, here is my simple function to copy the time of one date to another date using the old java.util.Calendar (inspire by Jigar Joshi) :
/**
* Copy only the time of one date to the date of another date.
*/
public static Date copyTimeToDate(Date date, Date time) {
Calendar t = Calendar.getInstance();
t.setTime(time);
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, t.get(Calendar.HOUR_OF_DAY));
c.set(Calendar.MINUTE, t.get(Calendar.MINUTE));
c.set(Calendar.SECOND, t.get(Calendar.SECOND));
c.set(Calendar.MILLISECOND, t.get(Calendar.MILLISECOND));
return c.getTime();
}
Calendar calendar = new Calendar.Builder()
.setDate(2022, Calendar.JUNE, 1)
.setTimeOfDay(0, 0, 0)
.build();
System.out.println(calendar.getTimeInMillis());
Related
I'm using "Asia/Bangkok" zone id.
That offset is from GMT UTC+07:00.
but when I did followings, then it is not +7:00 when set "01/01/1900 7:00:00.000"
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS");
Date date = dateFormat.parse("01/01/1900 7:00:00.000");
System.out.println(date);
System.out.println(date.getTimezoneOffset());
Date date2 = dateFormat.parse("01/01/1900 6:00:00.000");
System.out.println(date2);
System.out.println(date2.getTimezoneOffset());
The result is
Mon Jan 01 07:00:00 ICT 1900
-402
Mon Jan 01 06:00:00 ICT 1900
-420
I wondered if the offset had changed around 7:00 a.m. on January 1, 1900, so I looked it up on Wikipedia.
https://en.wikipedia.org/wiki/Time_in_Thailand
It was UTC+6:42, but from 1880 to 1920.
I have 3 questions.
Why it happen different time offset between "01/01/1900 7:00:00.000" and "01/01/1900 6:00:00.000"
Where can I see time zone history in Java.
How can I ignore different time offset in same Timezone.
-- additional question --
I understand that I should use LocalDateTime.
What is the best way to ignore offset and convert Date to LocalDateTime?
For example, in the following case, the value of convertedDate2 was converted based on an offset of -402.
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy H:mm:ss.SSS");
LocalDateTime originalLdate = LocalDateTime.parse("01/01/1900 7:00:00.000", dateFormatter);
LocalDateTime originalLdate2 = LocalDateTime.parse("01/01/1900 6:00:00.000", dateFormatter);
System.out.println(originalLdate);
System.out.println(originalLdate2);
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS");
Date date = dateFormat.parse("01/01/1900 7:00:00.000");
Date date2 = dateFormat.parse("01/01/1900 6:00:00.000");
LocalDateTime convertedDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime convertedDate2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(convertedDate);
System.out.println(convertedDate2);
LocalDateTime convertedDate3 = LocalDateTime.parse(dateFormat.format(date), dateFormatter);
LocalDateTime convertedDate4 = LocalDateTime.parse(dateFormat.format(date2), dateFormatter);
System.out.println(convertedDate3);
System.out.println(convertedDate4);
The result is
1900-01-01T07:00
1900-01-01T06:00
1900-01-01T07:00
1900-01-01T05:42:04
1900-01-01T07:00
1900-01-01T06:00
If I convert it once to String and then to LocalDateTime, as in convertedDate3 and convertedDate4,
then I could convert as my expectation, but I wonder this is the most efficient way or not?
Java runtime timezone information for each version is available here
https://www.oracle.com/java/technologies/tzdata-versions.html
Inside the linked file (for a specific version) you can find links to the actual data used
https://www.iana.org/time-zones/repository/releases/tzcode2021a.tar.gz
https://www.iana.org/time-zones/repository/releases/tzdata2021a.tar.gz
https://www.iana.org/time-zones/repository/releases/tzdb-2021a.tar.lz
Inside the tzdata*.tar.gz you can find a file called asia which contains the data for Bangkok as well.
It contains these entries
# Thailand
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Bangkok 6:42:04 - LMT 1880
6:42:04 - BMT 1920 Apr # Bangkok Mean Time
7:00 - +07
Link Asia/Bangkok Asia/Phnom_Penh # Cambodia
Link Asia/Bangkok Asia/Vientiane # Laos
So the -402 timezone should be used for all dates before 1/4/1920, but it seems the implementation is using the -402 offset only from 1/1/1900 0:00:00.000 UTC (from 1/1/1900 6:42:04.000 in your timezone) and until 1/4/1920 in your timezone and -420 otherwise. I am not sure, if that is intended or a bug.
How can I ignore different time offset in same Timezone.
If you are actually using timezones in your application, then you should not ignore them.
However, if you are making an application that is intended to be used just in your local timezone, then you can use a DateTime class without timezone information, such as java.time.LocalDateTime.
Also worth noting: even if these timezones would be correct, the historical dates might still be inaccurate, due to modern time rules being applied for all time (see below). So in the end it depends on what your use case is.
A date-time without a time-zone in the ISO-8601 calendar system. The ISO-8601 calendar system is the modern civil calendar system used today in most of the world. It is equivalent to the proleptic Gregorian calendar system, in which today's rules for leap years are applied for all time. For most applications written today, the ISO-8601 rules are entirely suitable. However, any application that makes use of historical dates, and requires them to be accurate will find the ISO-8601 approach unsuitable.
java.util.Date and java.text.SimpleDateFormat are very old classes. Although they mostly work, they are difficult to use properly, especially where timezones are concerned.
Date.getTimezoneOffset is deprecated. Do not use deprecated methods.
The proper way to work with timezone rules is using the java.time, java.time.zone, and java.time.format packages:
ZoneId zone = ZoneId.systemDefault();
DateTimeFormatter dateFormatter =
DateTimeFormatter.ofPattern("MM/dd/yyyy H:mm:ss.SSS");
LocalDateTime date =
LocalDateTime.parse("01/01/1900 7:00:00.000", dateFormatter);
System.out.println(date);
System.out.println(zone.getRules().getOffset(date));
LocalDateTime date2 =
LocalDateTime.parse("01/01/1900 6:00:00.000", dateFormatter);
System.out.println(date2);
System.out.println(zone.getRules().getOffset(date2));
The entire history of a timezone is in the ZoneRules:
System.out.println();
zone.getRules().getTransitions().forEach(System.out::println);
System.out.println();
zone.getRules().getTransitionRules().forEach(System.out::println);
You also asked:
What is the best way to ignore offset and convert Date to LocalDateTime?
You can’t. It is not possible to convert a Date to a LocalDateTime without assuming a timezone.
A Date is a wrapper for the number of milliseconds since 1970-01-01 00:00:00 UTC. You cannot generate a LocalDateTime from that without knowing which timezone to apply to that millisecond count. For example, noon Eastern Time in the US is a different number of milliseconds since 1970 than noon Greenwich time.
You may not realize it, but when you use SimpleDateFormat, you are specifying a timezone. Every SimpleDateFormat has a timezone property. Since your code never set that timezone explicitly, your date format used the system’s default timezone.
That is one reason to avoid DateFormat and SimpleDateFormat: the implicit use of the default timezone leads to errors and confusing behavior (though it is predictable behavior). When you use the java.time package and its subpackages, there is no ambiguity, and far less chance of confusion.
This question already has answers here:
Convert Java Date to UTC String
(7 answers)
Closed 5 years ago.
I set my Calendar instance to a UTC date at 00:00 however once i return the result its 1 hour ahead
Calendar cal = Calendar.getInstance(TIMEZONE_UTC, Locale.ENGLISH);
cal.set(2017, 12 - 1, 15);
cal.set(Calendar.AM_PM, Calendar.AM);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
System.out.println(cal.getTime());
// Fri Dec 15 01:00:00 CET 2017 but should be 00:00:00
I suppose there is the winter/summer offset but I didn't found any description in the Gregorian or Calendar Element to handle this issue
I am getting the impression that you are really after just the date of December 15, 2017, and just wanted to make sure that there is no unexpected hour-of-day? If so, LocalDate from java.time, the modern Java date and time API, is made for you:
LocalDate ld = LocalDate.of(2017, Month.DECEMBER, 15);
System.out.println(ld);
This prints
2017-12-15
No hours, minutes or seconds to be concerned about.
If you do need a date-time at 00:00 UTC (the time I used to call midnight until Basil Bourque’s comment), there are several ways to obtain it. One of them is:
OffsetDateTime utcDateTime = LocalDateTime.of(2017, Month.DECEMBER, 15, 0, 0)
.atOffset(ZoneOffset.UTC);
System.out.println(utcDateTime);
This prints
2017-12-15T00:00Z
The Z in the end means UTC or offset zero. You see that the time of day is 00:00 as you wanted.
The Calendar class that you used in the question is long outdated, so I recommend you don’t use it anymore. java.time, the modern Java date and time API also known as JSR-310, is so much nicer to work with.
What went wrong in your code?
While a Calendar does contain a time zone (you initialized it to TIMEZONE_UTC), a Date (another outdated class) doesn’t. So when you convert to Date using cal.getTime() you lose the information that you wanted the time to be in UTC. Next (and this confuses many), when you print the date, you implicitly call Date.toString(), and this method grabs your JVM’s time zone setting and produces a string with the time in this time zone. So apparently you are (like I am) in a time zone that is at UTC+01:00 in December. The following two date-times denote the same point on the timeline:
Fri Dec 15 01:00:00 CET 2017
Fri Dec 15 00:00:00 UTC 2017
The reason why you see local time printed is you're displaying it via an instance of Calendar using Date.toString() which uses the local timezone(implicitly use the system timezone).
I have a timestamp that I am trying to put into a Date object, however when I use Calendar, I am running into a strange problem. I seem to be able to unable to create a Date object with the values I want:
public static void main(String args[]){
Date today = new Date();
int hour = 4, min=0, sec=0, ms=64;
Calendar cal = GregorianCalendar.getInstance();
cal.clear();
cal.setTimeZone(TimeZone.getTimeZone("EDT"));
cal.setTime(today);
cal.set(Calendar.HOUR_OF_DAY,hour);
cal.set(Calendar.MINUTE,min);
cal.set(Calendar.SECOND,sec);
cal.set(Calendar.MILLISECOND,ms);
System.out.println("Time is: "+cal.getTime());
}
This produces:
Time is: Mon Jan 13 23:00:00 EST 2014
which is not the result I am looking for.
However, if I comment out the 'setTimeZone' method call, I get the following result:
Time is: Tue Jan 14 04:00:00 EST 2014
This is the result that I am looking for but I am concerned that if I am running on a machine that is not running in the same time zone, I will not get consistent behavior.
This is the result that I am looking for but I am concerned that if I am running on a machine that is not running in the same time zone
it is the problem. The internal representation should be ok, but it prints on local timezone: representation differs from real content.
use SimpleDateFormat http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html and set TimeZone to see the date on the Zone desired.
The problem here is that Java does not know of the timezone "EDT" (Eastern Daylight Time). As a result, Calendar seems to be setting the timezone to GMT.
The timezone needed here is "America/New_York" or "EST5EDT". When either of these values are used, the correct result is produced.
The list of valid Time Zones can be obtained by calling TimeZone.getAvailableIDs()
It is unfortunate that no warnings are produced when the requested Time Zone is not found.
If you can do away with java.util.Date, you can use joda time API to conveniently set these values as desired:
For your query, you can set your already created Calendar instance as a constructor parameter to DateTime.
DateTime dt = new DateTime(cal);
System.out.println(dt.toDateTimeISO());
Output:
2014-01-14T04:00:00.064-05:00
Calendar.getTime() returns a java.util.Date object. Date objects do not know anything about timezones. The Date object that Calendar.getTime() returns does not know to what timezone the Calendar that it came from is set.
When you print a Date object (for example, by implicitly calling toString() object, as you are doing) it is formatted in the default time zone of the machine you are running it on.
If you want to print a Date in a specific timezone, use a SimpleDateFormat, and set the desired timezone on the SimpleDateFormat object. For example:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("EDT"));
// Will display the date that the calendar is set to in the EDT timezone
System.out.println(df.format(cal.getTime()));
Java Date objects represent the number of milliseconds seconds since January 1, 1970, 00:00:00 GMT due to the fact that the other methods are deprecated. The two ways to "view" a Date object directly are "getTime()" and "toString()" (using "dow mon dd hh:mm:ss zzz yyyy"). Therefore, you are formatting the GMT value to your local timezone.
When working with dates, it is best to think of them as GMT values, and then as a "formatting" exercise when viewing the date.
For comparison, here is that same kind of code but using Joda-Time 2.3.
Avoid the java.util.Date & .Calendar classes.
Never use three-letter codes for time zones. They are neither standardized nor unique. Instead use proper time zone names. In this case, use "America/New_York" or "America/Montreal".
// Use time zone names, such as from this slightly outdated list: http://joda-time.sourceforge.net/timezones.html
DateTimeZone timeZone = DateTimeZone.forID( "America/New_York" );
// Input.
int hour = 4, min = 0, sec = 0, ms = 64;
// Start with now, then adjust the time of day.
DateTime now = new DateTime( timeZone );
DateTime dateTime = now.withHourOfDay( hour ).withMinuteOfHour( min ).withSecondOfMinute( sec ).withMillisOfSecond( ms );
// If needed, translate to a java.util.Date for use with other classes.
java.util.Date date = dateTime.toDate();
Dump to console…
System.out.println( "now: " + now );
System.out.println( "dateTime: " + dateTime );
System.out.println( "date: " + date );
When run…
now: 2014-01-20T21:04:51.237-05:00
dateTime: 2014-01-20T04:00:00.064-05:00
date: Mon Jan 20 01:00:00 PST 2014
I am trying to validate date using Simple date format so that i can put it into MySQL database
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd");
sdf.setLenient(false);
java.util.Date testDate = sdf.parse("2011-13-05");
System.out.println(testDate);
Gives output,
Wed Jan 05 00:13:00 GMT-06:00 2011
Can anyone explain why the date is being converted into time and thus preventing detection of an invalid month 13? Does java.util.date have a date object rather than a datetime object?
A modified version of my code will be greatly helpful.
You should use MM for month. mm is for minute in hour.
new SimpleDateFormat("yyyy-MM-dd");
Can anyone explain why the date is being converted into time and thus preventing detection of an invalid month 13?
Because your pattern specifies minutes rather than months. You want MM instead of mm. Whenever you have a SimpleDateFormat which isn't behaving as you expect it to, you should check your pattern against the documentation.
Does java.util.date have a date object rather than a datetime object?
No, but Joda Time does (LocalDate). Joda Time is a much cleaner date/time API, which separates out different concepts helpfully:
Instant (just a point in time - no time zone or calendar)
DateTime (date and time with a time zone and calendar)
LocalDate (just a date in a particular calendar)
LocalTime (just a time of day in a particular calendar)
LocalDateTime (date and time in a particular calendar)
There are some rough edges in terms of the API, but it's generally much better than java.util.Date and java.util.Calendar. The JSR-310 API which will be provided in Java 8 is different to both, but largely developed by one of the leaders of Joda Time, so there's a lot of conceptual overlap.
I cannot use Joda. When I try to create a Date or Calendar from a String representing a date or datetime in UTC, the resulting object has a timezone associated with it...
Here's the code:
Case 1:
SimpleDateFormat sdf = new SimpleDateFormat("yyyyDDD");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = sdf.parse("2012018");
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
cal.setTime(date);
System.out.println(cal.getTime()); //Tue Jan 17 19:00:00 EST 2012 !?!*&#&??
Case 2:
SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmm");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = sdf.parse("1202011431");
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
cal.setTime(date);
System.out.println(cal.getTime()); //Wed Feb 01 09:31:00 EST 2012 !?!*&#&??
Objects of type java.util.Date are an absolute amount of time since Epoch. When you create a Date object from a Calendar, it loses any TimeZone that the Calendar may have been using and just gives you a raw quantity of time. EST isn't really 'associated' with your Date, it's just that the toString method on Date uses the JVM default timezone to create a human readable representation.
It's important to understand that the usage of Calendar in the above code samples is doing absolutely nothing. Changing just the timezone like that changes only the human readable representation of that Calendar. The raw number of milliseconds since epoch is the same before and after you call setTime and getTime.
(All of the methods on java.util.Date that are related to human readable representations are deprecated and do not work properly, it is best to simply pretend they do not exist.)
When you print the time, it is always printed in local timezone configured on your machine and that is what you want (Store and represent date/time in UTC and convert to user specific timezone during presentation).
Yes, dates in Java have a time zone associated with them. The toString on a Date prints the date in the local timezone. If you do not want that, use a DateFormat to not show it. Note, that you will need to set the timezone on the DateFormat to UTC to get what you want.