We faced following problem:
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", java.util.Locale.GERMAN);
String dateInString = "06-04-1980";
Date date = formatter.parse(dateInString);
before: Sun Apr 06 00:00:00 CEST 1980
after: Sun Apr 06 01:00:00 CEST 1980
Another example:
Date date = Date.from(LocalDate.of(1980, 4, 6).atStartOfDay(ZoneId.systemDefault()).toInstant());
Facing the same problem.
We thought change of java11 to java17 is the problem, but it wasn't. It was the change of the timezone from Europe/Berlin to Europe Vienna. On 1980-04-06 the daylight saving time was established in Austria and the change of the hour was at 00:00. So there was no 00:00 at this date.
Reproduceable example - changing timezone to "Europe/Berlin" results in 0 hour.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
for (LocalDate date = LocalDate.of(1500, 04, 01); date.isBefore(LocalDate.of(9999, 1, 1)); date = date.plusDays(1)) {
Date out = Date.from(date.atStartOfDay(ZoneId.of("Europe/Vienna")).toInstant());
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Europe/Vienna")));
cal.setTime(out);
if (cal.get(Calendar.HOUR_OF_DAY) > 0) {
System.out.println(date.format(formatter) + " > " + cal.get(Calendar.HOUR_OF_DAY));
}
}
System.out.println("done");
All dates before 1893-03-31 have 23 as hour in timezone "Europe/Vienna", in "Europe/Berlin" its also 0.
It's not really a problem, it's a special thing about timezone "Europe/Vienna" which was changed in our system. If you get this problem, check your timezone, maybe it was changed by some other properties.
While summer time (DST) started at 02:00 o’clock in Germany on that date, it started already at midnight in Austria (Europe/Vienna time zone), so the time 00:00 did not exist, which is why we suddenly got 01:00. Both time zones are printed as CEST (Central European Summer Time), so the abbreviation does not allow us to distinguish.
I am in Israel, so in order to simulate the time zone of central Europe (using Java 17), I set the [System] property user.timezone to CET using the -D option of the java command. Then I ran the following code:
/*
* import java.time.ZoneId;
* import java.time.ZonedDateTime;
* import java.util.Date;
*/
ZonedDateTime zdt = ZonedDateTime.of(1980, 4, 6, 0, 0, 0, 0, ZoneId.systemDefault());
System.out.println(Date.from(zdt.toInstant()));
The result I got was:
Sun Apr 06 00:00:00 CET 1980
This is the result that you want, correct?
Related
I need to compare a certain date to the current date/time to make sure that it comes before the first day/hour/min/sec of the current month. In order to implement this feature, a configure a Calendar instance using its getActualMinimum method, however, today (Thursday, 19/01/2023 - 10:40:18 BRT 2023), it presented a behavior that I have never faced before. Consider the following code:
Calendar cal = Calendar.getInstance();
System.out.println("After instantiation: " + cal.getTime());
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
System.out.println("After configuring the Day of Month: " + cal.getTime());
cal.set(Calendar.HOUR_OF_DAY, cal.getActualMinimum(Calendar.HOUR_OF_DAY));
System.out.println("After configuring the Hour of day: " + cal.getTime());
cal.set(Calendar.MINUTE, cal.getActualMinimum(Calendar.MINUTE));
System.out.println("After configuring the Minutes: " + cal.getTime());
cal.set(Calendar.SECOND, cal.getActualMinimum(Calendar.SECOND));
System.out.println("After configuring the Seconds: " + cal.getTime());
cal.set(Calendar.MILLISECOND, cal.getActualMinimum(Calendar.MILLISECOND));
System.out.println("After configuring the Millis: " + cal.getTime());
The code above, in the moment that this post is being created, would print to the console:
After instantiation: Thu Jan 19 10:40:18 BRT 2023
After configuring the Day of Month: Sun Jan 01 10:40:18 BRT 2023
After configuring the Hour of day: Sat Dec 31 23:40:18 BRT 2022
After configuring the Minutes: Sat Dec 31 23:00:18 BRT 2022
After configuring the Seconds: Sat Dec 31 23:00:00 BRT 2022
After configuring the Millis: Sat Dec 31 23:00:00 BRT 2022
Could someone explain why, after configuring the Hour of day, the value was set to 23 and not 00?
Edit: I`m using Java 8, specifically JDK 1.8.0_241
My current and default Time Zone is the Horário Padrão de Brasília (BRT or GMT-3)
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API.
With java.time, the modern date-time API, you have specialized types for different purposes. A very common type is ZonedDateTime which contains the information of the timezone along with the date and time information.
Note: Unlike java.util date-time types, java.time types are immutable i.e. you always get a new instance on setting a new value; therefore, like a String, you need to assign the new value to the reference if you want the reference to point to the new value.
Demo:
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;
import java.util.Locale;
class Main {
public static void main(String[] args) {
// Replace ZoneId.systemDefault() with the applicable ZoneId e.g.
// ZoneId.of("America/New_York")
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.systemDefault());
System.out.println(zdt);
zdt = zdt.with(TemporalAdjusters.firstDayOfMonth());
System.out.println(zdt);
zdt = zdt.withHour(LocalTime.MIN.getHour());
System.out.println(zdt);
zdt = zdt.withMinute(LocalTime.MIN.getMinute());
System.out.println(zdt);
zdt = zdt.withSecond(LocalTime.MIN.getSecond());
System.out.println(zdt);
zdt = zdt.with(ChronoField.MILLI_OF_SECOND, LocalTime.MIN.getLong(ChronoField.MILLI_OF_SECOND));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
System.out.println(zdt.format(formatter));
// In a single statement
String output = ZonedDateTime.now(ZoneId.systemDefault())
.with(TemporalAdjusters.firstDayOfMonth())
.withHour(LocalTime.MIN.getHour())
.withMinute(LocalTime.MIN.getMinute())
.withSecond(LocalTime.MIN.getSecond())
.with(ChronoField.MILLI_OF_SECOND, LocalTime.MIN.getLong(ChronoField.MILLI_OF_SECOND))
.format(formatter);
System.out.println(output);
// There is a better way if all you want is day-1 with minimum time
zdt = LocalDate.now(ZoneId.systemDefault())
.with(TemporalAdjusters.firstDayOfMonth())
.atStartOfDay()
.atZone(ZoneId.systemDefault());
System.out.println(zdt.format(formatter));
}
}
Output from a sample run:
2023-01-19T16:50:43.811714Z[GMT]
2023-01-01T16:50:43.811714Z[GMT]
2023-01-01T00:50:43.811714Z[GMT]
2023-01-01T00:00:43.811714Z[GMT]
2023-01-01T00:00:00.811714Z[GMT]
2023-01-01T00:00:00.000Z
2023-01-01T00:00:00.000Z
2023-01-01T00:00:00.000Z
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
In case you need a solution using the legacy API:
Calendar#getTime returns an instance of java.util.Date which is not a real date-time object; rather, it just contains the number of milliseconds from January 1, 1970, 00:00:00 GMT. The Date#toString applies the system's timezone to calculate the date-time and returns the same.
The way to get the date-time string with the desired timezone is by applying the timezone to the SimpleDateFormat and using it to format the instance of java.util.Date.
Demo:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
class Main {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS z yyyy", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Calendar cal = Calendar.getInstance();
System.out.println("After instantiation: " + sdf.format(cal.getTime()));
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
System.out.println("After configuring the Day of Month: " + sdf.format(cal.getTime()));
cal.set(Calendar.HOUR_OF_DAY, cal.getActualMinimum(Calendar.HOUR_OF_DAY));
System.out.println("After configuring the Hour of day: " + sdf.format(cal.getTime()));
cal.set(Calendar.MINUTE, cal.getActualMinimum(Calendar.MINUTE));
System.out.println("After configuring the Minutes: " + sdf.format(cal.getTime()));
cal.set(Calendar.SECOND, cal.getActualMinimum(Calendar.SECOND));
System.out.println("After configuring the Seconds: " + sdf.format(cal.getTime()));
cal.set(Calendar.MILLISECOND, cal.getActualMinimum(Calendar.MILLISECOND));
System.out.println("After configuring the Millis: " + sdf.format(cal.getTime()));
}
}
Output from a sample run:
After instantiation: Thu Jan 19 15:29:38.381 UTC 2023
After configuring the Day of Month: Sun Jan 01 15:29:38.381 UTC 2023
After configuring the Hour of day: Sun Jan 01 00:29:38.381 UTC 2023
After configuring the Minutes: Sun Jan 01 00:00:38.381 UTC 2023
After configuring the Seconds: Sun Jan 01 00:00:00.381 UTC 2023
After configuring the Millis: Sun Jan 01 00:00:00.000 UTC 2023
ONLINE DEMO
Probably this is caused by the default TimeZone of your PC , try adding this after you declare the Calnedar object
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
I want to precisely calculate the time one week from a given date, but the output I get back is one hour early.
code:
long DURATION = 7 * 24 * 60 * 60 * 1000;
System.out.println(" now: " + new Date(System.currentTimeMillis()));
System.out.println("next week: " + new Date(System.currentTimeMillis() + DURATION));
output:
now: Wed Sep 16 09:52:36 IRDT 2015
next week: Wed Sep 23 08:52:36 IRST 2015
How can I calculate this correctly?
Never, ever rely on millisecond arithmetic, there are too many rules and gotchas to make it of any worth (even over a small span of time), instead use a dedicated library, like Java 8's Time API, JodaTime or even Calendar
Java 8
LocalDateTime now = LocalDateTime.now();
LocalDateTime then = now.plusDays(7);
System.out.println(now);
System.out.println(then);
Which outputs
2015-09-16T15:34:14.771
2015-09-23T15:34:14.771
JodaTime
LocalDateTime now = LocalDateTime.now();
LocalDateTime then = now.plusDays(7);
System.out.println(now);
System.out.println(then);
Which outputs
2015-09-16T15:35:19.954
2015-09-23T15:35:19.954
Calendar
When you can't use Java 8 or JodaTime
Calendar cal = Calendar.getInstance();
Date now = cal.getTime();
cal.add(Calendar.DATE, 7);
Date then = cal.getTime();
System.out.println(now);
System.out.println(then);
Which outputs
Wed Sep 16 15:36:39 EST 2015
Wed Sep 23 15:36:39 EST 2015
nb: The "problem" you seem to be having, isn't a problem at all, but simply the fact that over the period, your time zone seems to have entered/exited day light savings, so Date is displaying the time, with it's correct offset
Try this
Calendar cal = Calendar.getInstance();
System.out.println(cal.getTime());
cal.add(Calendar.DAY_OF_MONTH, 7);
System.out.println(cal.getTime());
The difference is because of the different timezone. IRDT is +0430 and IRST is +0330
To overcome this issue you can use the JodaTime.
LocalDateTime now = LocalDateTime.now();
LocalDateTime nextweek = now.plusDays(7);
System.out.println(now);
System.out.println(nextweek);
As other said. It would be better to use Calendar or JodaTime library. But the question is why you were not getting the desired result. It was because currentTimeMillis() calculates time between "computer time" and coordinated universal time (UTC). Now consider following case.
long DURATION = 7 * 24 * 60 * 60 * 1000;
Date now = new Date();
Date nextWeek = new Date(now.getTime() + DURATION);
System.out.println(" now: " + now);
System.out.println("next week: " + nextWeek);
here Date.getTime() calculate time from 00:00:00 GMT every time and then when converted to string will give time for your local time zone.
Edit :
I was wrong. The reason is as simon said.
The actual "why" is that IRDT (Iran Daylight Time) ends on September
22nd. That's why the first date (September 16th) in the OP's post is
displayed as IRDT and the second date (September 23rd) is displayed as
IRST. Because IRST (Iran Standard Time) is one hour earlier than IRDT
the time displayed is 08:52:36 instead of 09:52:36.
I have the method
public static void testDateFormat() throws ParseException {
DateFormat dateFormat=new SimpleDateFormat("HH:mm:ss");
Date hora;
hora=dateFormat.parse("00:00:01");
System.out.println(hora.getHours()+" "+hora.getMinutes());
System.out.println("Date "+hora);
System.out.println("Seconds "+TimeUnit.MILLISECONDS.toSeconds(hora.getTime()));
}
The output is
0 0
Date Thu Jan 01 00:00:01 COT 1970
Seconds 18001
Why the number of seconds is 18001? I expected to get 1 second.
Because your Date has a TimeZone that is not UTC. It is, in fact, COT - which is UTC-5. And 5*60*60 is 18000 (or your result, plus one second). To get the value you expect, you could call DateFormat#setTimeZone(TimeZone) like,
DateFormat dateFormat=new SimpleDateFormat("HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); // <-- Add this.
Date hora=dateFormat.parse("00:00:01");
System.out.println(hora.getHours()+" "+hora.getMinutes());
System.out.println("Date "+hora);
System.out.println("Seconds "+TimeUnit.MILLISECONDS.toSeconds(hora.getTime()));
Output is as you expect.
Edit
As noted in the comments, Date#getTime() per the Javadoc
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.
And your Date of
Thu Jan 01 00:00:01 COT 1970
is equivalent to
Thu Jan 01 00:05:01 UTC 1970
and thus you get the 5 hour difference.
The answer by Elliott Frisch is correct.
Time-Only
But if you are working with time-only without date or time zone, then use a date-time library that can handle that explicitly rather than hacking the java.util.Date class.
LocalTime
Use either the Joda-Time library or the java.time package in Java 8. Both offer a LocalTime class.
LocalTime localTime = LocalTime.parse( "00:00:01" );
int minuteOfHour = localTime.getMinuteOfHour();
I'm trying to create a function that convert a timestamp to Date object.
My problem is that using this online tools i reach correctly to convert timestamp to date but using java it doesn't convert correctly.
This is what i try:
public static Date getDateFromUUID(UUID uuid) {
Calendar uuidEpoch = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
uuidEpoch.clear();
uuidEpoch.set(1582, 9, 15, 0, 0, 0);
long epochMillis = uuidEpoch.getTime().getTime();
long time = (uuid.timestamp() / 10000L) + epochMillis;
Calendar start = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Calendar end = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
start.setTimeInMillis(time*1000);
end.set(start.get(Calendar.YEAR), start.get(Calendar.MONTH), start.get(Calendar.DAY_OF_MONTH),0,0,0);
return end.getTime();
}
I'm trying using that uuid: a261ae00-2a9c-11b2-ae56-bcee7be23398
it correctly converts to timestamp : 1406412000
Using this:
Calendar start = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Calendar end = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
start.setTimeInMillis(time*1000);
end.set(start.get(Calendar.YEAR), start.get(Calendar.MONTH), start.get(Calendar.DAY_OF_MONTH),0,0,0);
return end.getTime();
I need to remove hours, minutes and seconds and take only years,months and days.
but it convert timestamp to
Sat Jul 26 02:00:00 CEST 2014
Instead of
Sun Jul 27 00:00:00 CEST 2014
what could be my mistake?
Thanks!
Your time zone if wrong. Notice that output is CEST but you set the calendar to UTC. The delta between these two is 2 hours. When you output the Date you need to set the timezone appropriately.
I have a date string of format MM/dd/yyyy that I am parsing using SimpleDateFormat
Now say the startDateString is 11/26/2012 for the code given below. I set the time zone to America/New_York
SimpleDateFormat df=new SimpleDateFormat("MM/dd/yyyy");
Date st = df.parse(startDateString);
Calendar startDate = Calendar.getInstance(TimeZone.getTimeZone("America/New_York"));
System.out.println("BEFORE : Start Date :"+startDate.getTime());
startDate.setTime(st);
System.out.println("AFTER : Start Date :"+startDate.getTime());
DateTimeZone timezone = DateTimeZone.forID("America/New_York");
DateTime actualStartDate = new DateTime(startDate,timezone);
System.out.println("JODA DATE TIME "+ actualStartDate);
The outout of above code snippet:
BEFORE : Start Date :Tue Nov 27 12:26:51 IST 2012
AFTER : Start Date :Mon Nov 26 00:00:00 IST 2012 //ok it sets date to 26th
//with all time parameters as 0.
JODA DATE TIME 2012-11-25T13:30:00.000-05:00 // here the date and
// time parameter are changed
What my problem is when I create my actualStartDate like this :
DateTime actualStartDate = new DateTime(startDate,timezone);
The date changes to 25 and the time changes to 13:00:00
I think this is because of timezone zone difference between India and US (total -10:30 from IST Indian time)
What I want is JODA DATE TIME 2012-11-26T00:00:00.000-05:00
Do I manually set the parameters of time inside my startDate calendar instance to 0 ?
I suspect the problem is that you're parsing in your default time zone. This:
AFTER : Start Date :Mon Nov 26 00:00:00 IST 2012
shows that the instant in time you're using is midnight IST - not midnight in New York or in UTC. Currently IST is 18:30 in UTC, so the instant you're representing is 25-11-25T18:30:00Z.
When you convert that into New York time, you end up with 2012-11-25T13:30:00-05:00, which is exactly what Joda Time is doing.
I would strongly advise that:
You avoid using the Java libraries at all (that's where all the problems have come from here - both in parsing, and the result of Date.toString() confusing you)
You use LocalDate to represent a date, rather than DateTime. You're trying to represent a date after all, not an instant in time. This bypasses time zones entirely, as a date doesn't have a time zone.
Sample code:
import java.util.*;
import org.joda.time.*;
import org.joda.time.format.*;
public class Test {
public static void main (String[] args) {
String text = "11/26/2012";
DateTimeFormatter formatter =
DateTimeFormat.forPattern("MM/dd/yyyy")
.withLocale(Locale.US);
LocalDate date = formatter.parseLocalDate(text);
System.out.println(date);
}
}
Once you've got a LocalDate, if you want to find out the instant at which that day started in a particular time zone, you can use LocalDate.toDateTimeAtStartOfDay(DateTimeZone).