I got simple code, maybe the problem relies on the given format string or on the timezone. So here is the code:
public static void main(String[] args) {
SimpleDateFormat df = new SimpleDateFormat("HH:mm");
try {
Date added = df.parse("00:00");
System.out.println(added);
System.out.println(added.getTime());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The result is:Thu Jan 01 00:00:00 EET 1970
-10800000 --> should be 0 as we give 00:00 hours in and the other time elements remain default.
//Edit
Yes the problem is with timezone to fix this use
df.setTimeZone(TimeZone.getTimeZone("UTC")); before parsing.
The value 10800000 is exactly 3 hours (in milliseconds), which I'm gathering is roughly the offset between EET and UTC (actually, it's only 2 hours according to this, but I guess the extra hour's down to DST or something).
Therefore, the difference is probably due to your timezone.
Your timezone appears to be EET. That difference would be the offset from 1st Jan 1970 00:00:00.000 UTC
Since you didn't specify the date, only the hour, you actually created a Date object with default values, as specified in the DateFormat API (which SimpleDateFormat implements):
The date is represented as a Date object or as the milliseconds since January 1, 1970, 00:00:00 GMT.
Related
I need to get the today midnight time as milliseconds. For example, today's date is 2020-03-20 and I convert this today midnight as milliseconds using the below code. If it works fine in my local environment, but the problem is when I deploy this code to the server, the server has UTC time zone, So even I pass the timezone, the milliseconds returned is wrong. After debugging I found out that this is happening due to parsing the Date, the date uses the default timeZone. I tried to set the timeZone in the Date, but the millisecond value returning is wrong even the date is 2020/03/20 00:00:00. For you to understand more below are some cases.
In the local Environment: Time Zone pass to method = "Asia/Colombo"
Date in milliseconds = 1584642600000
Converted date = Fri Mar 20 2020 00:00:00
In the Server Environment: Time Zone pass to method = "Asia/Colombo"
Date in milliseconds = 1584662400000
Converted date = Fri Mar 20 2020 05:30:00
Note that here Time Zone is the value I pass to my method parameter. I'm using java 8.
private static final String DATE_FORMAT = "yyyy/MM/dd 00:00:00";
private long getTMT(String timeZone) {
try {
ZoneId zoneId = ZoneId.of(timeZone);
ZonedDateTime currentZone = ZonedDateTime.now(zoneId);
ZonedDateTime zonedDateTime =
currentZone.withZoneSameInstant(zoneId);
DateTimeFormatter format =
DateTimeFormatter.ofPattern(DATE_FORMAT);
String formattedDateTime = zonedDateTime.format(format);
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
Date date = sdf.parse(formattedDateTime);
return date.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
}
Hope I explained my question clearly, please let me know your answers/comments on this.
Thank you.
Formatting to string and then parsing from it is a horrible solution, especially since you also have to also construct all these parsers every time, and your format effectively has hacks in it.
There are simpler ways to both construct a midnight ZDT:
ZonedDateTime zdt = LocalDate.now(zoneId).atTime(LocalTime.MIDNIGHT).atZone(zoneID);
And then extracting the epoch-millis value from it:
long epoch = zdt.toInstant().toEpochMilli();
Alternatively, since you know that milliseconds and nanoseconds are always 0 at midnight, this is marginally faster:
long epoch = zdt.toEpochSecond() * 1000;
The second approach wouldn't work if your time is arbitrary, as it will always ignore milli-of-second value.
I am generating epoch timestamp in milliseconds with the following code and it works (verified with https://www.epochconverter.com/). However, when we are setting timezone with JVM option -Duser.timezone=America/Toronto then for some historical dates time offset is differ by one hour. i.e Date=1950-11-19 (yyyy-MM-dd) correct epoch milliseconds -603313200000 (Sunday, November 19, 1950 12:00:00 AM GMT-05:00) but when timezone is set with JVM options value is -603316800000 and Epoch converted shows Saturday, November 18, 1950 11:00:00 PM GMT-05:00. I have used joda time lib with JDK 10
def static Long getEpochTimeStampInMilliSeconds(String simpleDate, String dateFormat) {
Long retVal = null
try {
org.joda.time.format.DateTimeFormatter fmt = DateTimeFormat.forPattern(dateFormat)
DateTimeZone dtz2 = DateTimeZone.forID("America/Toronto")
DateTime parsedDateTime = DateTime.parse(simpleDate, fmt).withZone(dtz2)
retVal = parsedDateTime.getMillis()
} catch (Exception e) {
retVal = null
}
return retVal
}
date format is : "yyyy-MM-dd"
You need to parse with the correct time zone, so instead of calling dateTime.withZone(...) after parsing is done, you need to call dateTimeFormatter.withZone(...) before parsing with the formatter.
If the default time zone, as set by the user.timezone system property is America/Toronto, then the parsed DateTime value is already in that time zone, and dateTime.withZone(...) will do nothing.
If the default time zone is something else, then the parsed DateTime value is in that time zone, which would be a different UTC epoch millisecond value. Calling dateTime.withZone(...) will change the time zone, and hence the time value, but will not change the UTC epoch millisecond value.
def dtz2 = org.joda.time.DateTimeZone.forID("America/Toronto")
def fmt = org.joda.time.format.DateTimeFormat.forPattern(dateFormat).withZone(dtz2)
retVal = org.joda.time.DateTime.parse(simpleDate, fmt).getMillis()
UPDATE
From comment:
I am receiving -603316800000 for 1950-11-19 for all scenario but correct value is -603313200000
Lets test which value is correct, using Java-Time API:
ZoneId zone = ZoneId.of("America/Toronto");
System.out.println(Instant.ofEpochMilli(-603316800000L));
System.out.println(Instant.ofEpochMilli(-603316800000L).atZone(zone));
System.out.println(Instant.ofEpochMilli(-603313200000L));
System.out.println(Instant.ofEpochMilli(-603313200000L).atZone(zone));
Output
1950-11-19T04:00:00Z
1950-11-19T00:00-04:00[America/Toronto] ⬅ Correct value
1950-11-19T05:00:00Z
1950-11-19T01:00-04:00[America/Toronto]
As you can see, the value you get (-603316800000) is the correct value for 1950-11-19 at midnight, Toronto time.
You get offset -04:00 for Toronto, because in 1950, DST lasted until Sun, Nov 26 at 2:00 am (see https://www.timeanddate.com/time/zone/canada/toronto), so the offset is correct for Eastern Daylight Time (EDT).
Don't know why you think -603313200000 is the correct value, but it is not.
I have a string that looks like this
Aug 16, 2013,11:30:10
The comma can be replaced by a different separator and the date & time position can be switched.
I am trying to use this format for my SimpleDateFormat(dtString is the String above):
Date d = null;
try {
d = new SimpleDateFormat("MMMM dd, yyyy,hh:mm:ss", Locale.ENGLISH).parse(dtString);
} catch (ParseException ex) {
Logger.getLogger(MonKaiClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
return d;
but when I run d.getYear() the result is 113.
All of the other Date methods return the correct result except .getYear(). Am I missing something? Is my SimpleDateFormatter wrong?
You should not use Date#getYear. It's deprecated.
As for the result you get, it's as specified in the Javadoc:
Returns a value that is the result of subtracting 1900 from the year that contains or begins with the instant in time represented by this Date object, as interpreted in the local time zone.
Use Calendar API instead. Or even better, if you can use 3rd party library, then I would really suggest you to try Joda Time. Or wait for Java 8 to come next year, that has a new Date Time API.
Simple way to check the result of SimpleDateFormat parsing is this
System.out.println(d);
and it shows correct result
Fri Aug 16 11:30:10 EEST 2013
the problems is that Date methods interpreting year, month, day, hour, minute, and second are deprecated. See Date API
I have following method which convert my custom DMY (date,month,year) object to Date.
public static Date serverCreateDateFromDMY(DMY pDMY, TimeZone pTimeZone)
{
Calendar vCalendar = Calendar.getInstance(pTimeZone);
vCalendar.set(Calendar.YEAR, pDMY.getYear());
// Below line is because DMY month counts are 1-indexed
// and Date month counts are 0-indexed
vCalendar.set(Calendar.MONTH, pDMY.getMonthOfYear() - 1);
vCalendar.set(Calendar.DAY_OF_MONTH, pDMY.getDayOfMonth());
System.out.println(vCalendar.getTime());
TimeUtilsServer.zeroCalendarHoursAndBelow(vCalendar);
System.out.println(vCalendar.getTime());
return vCalendar.getTime();
}
public static void zeroCalendarHoursAndBelow(Calendar pToZero)
{
pToZero.set(Calendar.HOUR_OF_DAY, 0);
pToZero.set(Calendar.MINUTE, 0);
pToZero.set(Calendar.SECOND, 0);
pToZero.set(Calendar.MILLISECOND, 0);
}
to serverCreateDateFromDMY() method, I am passing these arguments : DMY=20120424, and TimeZone is : America/New_York. Application is running locally in my timezone which is IST.
based in above inputs, following output is printed.
Tue Apr 24 14:43:07 IST 2012
Tue Apr 24 09:30:00 IST 2012
so as you see that in last output time is not zeroed out. any suggestions please?
#Marko, yes I come to know about DateFormat and I tried following example. but still date is printed with time and not zeroing out.
TimeZone tz = TimeZone.getTimeZone("America/New_York");
Calendar vCalendar = Calendar.getInstance(tz);
vCalendar.set(Calendar.YEAR, 2012);
vCalendar.set(Calendar.MONTH, 4 - 1);
vCalendar.set(Calendar.DAY_OF_MONTH, 24);
DateFormat df = DateFormat.getDateTimeInstance();
df.setTimeZone(tz);
System.out.println(df.format(vCalendar.getTime()));
vCalendar.set(Calendar.HOUR_OF_DAY, vCalendar.getActualMinimum(Calendar.HOUR_OF_DAY));
vCalendar.set(Calendar.MINUTE, vCalendar.getActualMinimum(Calendar.MINUTE));
vCalendar.set(Calendar.SECOND, vCalendar.getActualMinimum(Calendar.SECOND));
vCalendar.set(Calendar.MILLISECOND, vCalendar.getActualMinimum(Calendar.MILLISECOND));
System.out.println(df.format(vCalendar.getTime()));
java Date / Time API have a bad design from the time of its creation. Maybe you should take a look at some library - for example this which hides JDK API deficiencies - http://joda-time.sourceforge.net/
Internally, Date and Calendar objects are stored in UTC. When you set the fields to 0, the Calendar is updated in UTC.
When you ask the Calendar for the time, it then converts the Date to your desired Timezone, hence the difference.
... and you are 9:30h ahead of NY time. You set the time to midnight NY time and read it out as time in your zone. Note that getTime returns a Date, which is not timezone-configurable. You'll need DateFormat if you want to specify the timezone for which you print the result.
I've written a method that returns the milisecond value of a string formatted date, and for some reason it's giving me dates 39000 years in the future. any ideas why?
private long getTimeInMs(String currentStartTimeString) {
//String newDateString = currentStartTimeString.substring(6,10)+"-"+currentStartTimeString.substring(3, 5)+"-"+currentStartTimeString.substring(0, 2)+ "T" + currentStartTimeString.substring(11);
String newDateString = currentStartTimeString.substring(0,19);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long timeInMs;
try {
timeInMs = df.parse(newDateString).getTime();
} catch (ParseException e) {
log.error("Failed to parse current Start Time",e);
return 0;
}
return timeInMs;
}
If I enter the date string "2009-07-07 10:51:01.15" it returns 1246960261000 which is actually Wed Aug 06 41484 11:16:40 GMT+0100 (GMT Daylight Time)
Okay I think the issue is that it's giving ms past the Java epoc and I'm evaluating it against the unix epoch...
I'm guessing that you interpreted the returned value from getTime() as if it was a Unix time_t value. It's not - it's milliseconds past the Java epoch, not seconds past the Unix epoch.
It looks fine to me. The Date object that comes out of the parse toString's to "Tue Jul 07 10:51:01 BST 2009" (I'm in the UK timezone here), but that should make no big difference). The millis value of 1246960261000 is correct, why do you think that evaluates to the far future? How did you calculate that?
The value is correct, in fact :
(((((1246989061000 / 1000) / 60)/60)/24)/365)
gives
39.54176373033992 years which is about correct given that 0 is 1970.
running your code in Java 6, i get 1246978261000, which turns out to be correct.
System.out.println(new Date(timeInMs));
returns
Tue Jul 07 10:51:01 EDT 2009
edit:
to confirm others' suggestions that you are looking at seconds (not millis):
System.out.println(new Date(timeInMs*1000));
yields
Mon Mar 02 13:16:40 EST 41485