So I'm kinda new to the Calendar/Time/Date stuff in Java but I've read a lot about them on the net.
Here is what I have to do:
I have an external device which sends an Avl Data Packet to my Communication Server and I'm on the parsing process of the Data part.
Somewhere in the Data Packet the device sends a timestamp of 32 bits which I have to parse/translate into the time the Record of the point from the GPS was saved.
The timestamp gives me seconds from 2007.01.01 00:00 UTC
Now here is a sample code that I felt that was the closest one I tried of the rest of the experiments..
DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS");
long now = (long)(TimeStampSeconds.longValue() * 1000);
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(2007, 0, 1);
calendar.setTimeInMillis(now);
System.out.println(now + " = " + formatter.format(calendar.getTime()));
After that I found out that the calendar.set doesnt make a new epoch and so the .setTimeInMills doesnt work.Though I get some crazy results like:
Binary Timestamp is : 0000101011000001010110001111011100001111
SECONDS: 46193506063
46193506063000 = 25/10/3433 04:27:43.000
Shouldn't I just be missing just the 37 years between 1970 and 2007??
I want to find a way of finding the time from the seconds I get from the device but they have epoch 1/1/2007 and java has epoch 1/1/1970..
EDIT: What I want is to have time:1/1/2007 PLUS the timestamp's time. Hope I clarified the question a bit..
Someone any ideas??
Thx in Advance
It seems what you want to do is just to add your now value to the Calendar. This is easily done:
DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS");
long now = (long)(TimeStampSeconds.longValue() * 1000);
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(2007, 0, 1);
calendar.setTimeInMillis(calendar.getTimeInMillis() + now);
System.out.println(now + " = " + formatter.format(calendar.getTime()));
EDIT
Something is weird regarding what your now variable holds. 46193506063 seconds corresponds to 1464.786468258 years according to this time converter.
Assuming you read the input in a timestamp long variable, I'd do something like:
Calendar theirEpoch = Calendar.getInstance();
theirEpoch.set(2007, 0, 1);
Calendar myEpoch = Calendar.getInstance();
myEpoch.set(1970, 0, 1);
long difference = myEpoch.getTimeInMillis() - theirEpoch.getTimeInMillis();
Calendar result = Calendar.getInstance();
result.setTimeInMillis(timestamp + difference);
I didn't test it, but it should give you the idea. Note also that I didn't take time zones into account.
This is the correct way to do what you want:
Calendar cal = Calendar.getInstance();
cal.set(2007, 1, 1, 0 ,0 ,0);
cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.MILLISECOND, theirEpoch);
If their epoch is in seconds, change the last MILISECOND to SECOND.
The easiest thing to do is to use the roll() method of Calendar after setting the time in milliseconds:
calendar.roll(Calendar.YEAR, 37) --> just adds 37 years to your date ;-)
But I think your input data is wrong : if you take the number of seconds that have past since 01/01/2007 until now , it should be about 200 million and not 40 billion like in your example ...
Related
I have a misundertood managing dates in Java when I want to calculate the span in number of days between two dates.
Say we have two different dates:
Date 1: 1986-01-24
Date 2: 2017-04-20
Case 1: I have this snippet of code using Dates:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date dt1 = format.parse("1986-01-24");
Date dt2 = format.parse("2017-04-20");
int intSpanInDays= (int) ((dt2.getTime() - dt1.getTime()) / (1000 * 60 * 60 * 24));
System.out.println("Days between: " + intSpanInDays);
Output 1:
Days between: 11408
Case 2: Snippet of code using Calendar:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
GregorianCalendar cal1 = new GregorianCalendar();
cal1.setTime(format.parse("1986-01-24"));
cal1.set(Calendar.HOUR, 0);
cal1.set(Calendar.MINUTE, 0);
cal1.set(Calendar.SECOND, 0);
GregorianCalendar cal2 = new GregorianCalendar();
cal2.setTime(format.parse("2017-04-20"));
cal2.set(Calendar.HOUR, 0);
cal2.set(Calendar.MINUTE, 0);
cal2.set(Calendar.SECOND, 0);
long spanInMillis = cal2.getTimeInMillis() - cal1.getTimeInMillis();
GregorianCalendar cal3 = new GregorianCalendar();
cal3.setTimeInMillis(spanInMillis);
long millisInADay = 1000 * 60 * 60 * 24;
System.out.println("Days between: " + (cal3.getTimeInMillis() / millisInADay));
Output 2:
Days between: 11408
Case 3: Example using a spreadsheet in Excel:
When I use MS Excel to get this span just introducing the given dates and simply substracting, the output is this:
QUESTION
Why is Java calculation code of date missing one day? What is missing or wrong in either case 1 and 2 that does not match the result in case 3?
The spreadsheet is taking Daylight Savings into account, and your calculations are naively truncating, and given that there's one more 23-hour day in the interval than 25-hour days, the 23-hour remainder is truncated, yielding a result one day less than the correct answer.
JDK 8 largely simplifies these calculations with its new date time API. The same can be done accurately and simply using the below code :
LocalDate date1 = LocalDate.of(1986, 01, 24);
LocalDate date2 = LocalDate.of(2017, 04, 20);
System.out.println(date1.until(date2, ChronoUnit.DAYS));
This automatically takes care of any/all the DST changes, leap years etc. which is mostly missed when trying to do the calculations manually.
private long calculateRemainingDays() {
final Calendar c = Calendar.getInstance();
c.set(2015, 7, 23);
final Calendar today = Calendar.getInstance();
final long millis = c.getTimeInMillis()
- today.getTimeInMillis();
// Convert to days
final long days = millis / 86400000;
return days;
}
I need to add a function in my android application. I want a remaining days from current day to 2015/9/30. When the date is change to next day, the remaining days will decrease. I would like to say like that:
7 days remaining... 6/5/4/etc... Please help me to get correct remaining days. Sorry for my poor english. Thanks!
Use Calender.JULY instead of 7 in the parameters for the set() method.
7 = August.
6 = July.
As it starts with January as 0. It's better to use the static instance variables like Calender.JANUARY.
But as you want to calculate till 2015/9/30, you should set the value as
c.set(2015, Calender.SEPTEMBER, 09);
The rest of the code seems ok. It will return the correct number of days.
Try this :-
final long millis = c.getTimeInMillis()
- today.getTimeInMillis();
System.out.println ("Days: " + TimeUnit.DAYS.convert(millis , TimeUnit.MILLISECONDS));
if you don't mind using joda.time
you can do something of this form:
final Calendar c = Calendar.getInstance();
c.set(2015, Calender.SEPTEMBER, 30);
Date endDate = c.getTime();
Instant startInstant = new Instant(new Date());
Instant endInstant = new Instant(endDate);
Days days = Days.daysBetween(startInstant, endInstant);
I am extracting a timestamp out of Excel (2010):
It is displayed as "10.06.2015 14:24". The "internal representation" of excel is "42165.6". Last one is outputted from Excel.
So, for now, I want to parse this timestamp into a Java program like this:
double input = 42165.6;
// long myLong = ???
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm");
System.out.println(sdf.format(new java.sql.Date(myLong)));
How can I do this in line 2?!
Many thanks for your help!!!
Kind regards
Excel stores dates as the number of days since January 1900. This makes it awkward to convert into a Java date (milliseconds since 1 Jan 1970). If you cannot export it in a readable format, you'll need to create a Java Calendar, set it to 1 Jan 1900, and add the number of days.
Here it is:
double excelDate = 42165.6;
int days = (int) excelDate; //number of days
int seconds = (int) ((excelDate-days) * 86400); //number of seconds in .6 days
//create calendar set to 01-Jan-1900
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1900);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 1);
//Add days and seconds to get required date/time
cal.add(Calendar.DATE, days-1);
cal.add(Calendar.SECOND, seconds);
//cal.getTime() returns a java.util.Date, print it out...
System.out.println(cal.getTime());
NOTE
A java.sql.Date can be created from a java.util.Date as follows:
java.util.Date utilDate = ....
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
The fastest way to get from the excel notation to a java.sql.Date is:
double excelInput = 42165.6;
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm");
System.out.println("---> "
+ sdf.format(new java.sql.Date(
(long) ((excelInput - 25569) * 86400 * 1000))));
Excel stores a date since 01-01-1900, java.sql.date since 01-01-1970. There are exactly 25569 days difference between both dates. The constructor of java.sql.Date wants the milliseconds (!) since 01-01-1970, so with "* 86400" we get the seconds and then with (* 1000) the milliseconds.
That's it! ;)
Putting 42165.6 in excel and formatting to a date gives the correct date 6/10/15 14:24.
For me the answers by mrbela and NickJ both gave incorrect answers to the question of 42165.6, 06/10/2015 09:23 and 06/12/2015 03:25. This seems to be true of most of the examples I've tried.
The solution that worked for me was to use Apache POI, which is a java API for Microsoft Documents. This question is very similar and had the pointers that led me to poi.
Here is a working code example.
double input = 42165.6;
Date date = DateUtil.getJavaDate(input);
System.out.println(new SimpleDateFormat("dd.MM.yyyy HH:mm").format(javaDate));
which outputs the correct 06/10/2015 14:24
I have a GregorianCalendar that I am am trying to set the time on. I am getting the date from one calendar and the time from another calendar. It mostly works, except for the 2AM hour of the DST switch day.
For example, with a date of 3/10/2013, a time of 2:40AM and a target output of 3/10/2013 2:40AM, I get 3/10/2013 3:40AM:
GregorianCalendar reportingDate = //some instance with a relevant date (in this case 3/10/2013)
GregorianCalendar targetTime = //some instance with a relevant time (in this case 2:40AM)
Calendar combination = Calendar.getInstance();
combination.set(Calendar.YEAR, reportingDate.get(Calendar.YEAR));
combination.set(Calendar.MONTH, reportingDate.get(Calendar.MONTH));
combination.set(Calendar.DAY_OF_YEAR, reportingDate.get(Calendar.DAY_OF_YEAR));
combination.set(Calendar.HOUR, targetTime.get(Calendar.HOUR));
combination.set(Calendar.AM_PM, targetTime.get(Calendar.AM_PM));
combination.set(Calendar.MINUTE, targetTime.get(Calendar.MINUTE));
combination.set(Calendar.SECOND, targetTime.get(Calendar.SECOND));
As soon as the code sets the AM_PM on the combination Calendar the time switches to 3:40AM. I would like it to not switch. I think this has to do with the target time Calendar being created as a time on the epoch date, but I would like the target time's specific date to not really matter...
Based on this output... I would think this is just how Java deals with DST? Seems like 2-3 AM goes into oblivion
See my comment below
final Calendar reportingDate = Calendar.getInstance();
reportingDate.set(Calendar.YEAR, 2013);
reportingDate.set(Calendar.MONTH, Calendar.MARCH);
reportingDate.set(Calendar.DAY_OF_MONTH, 10);
final Calendar targetTime = Calendar.getInstance();
targetTime.set(Calendar.AM_PM, Calendar.AM);
targetTime.set(Calendar.HOUR_OF_DAY, 3);
targetTime.set(Calendar.MINUTE, 0);
targetTime.set(Calendar.SECOND, 0);
targetTime.set(Calendar.MILLISECOND, 0);
final Calendar combination = Calendar.getInstance();
combination.set(Calendar.YEAR, reportingDate.get(Calendar.YEAR));
combination.set(Calendar.MONTH, reportingDate.get(Calendar.MONTH));
combination.set(Calendar.DAY_OF_YEAR, reportingDate.get(Calendar.DAY_OF_YEAR));
combination.set(Calendar.HOUR, targetTime.get(Calendar.HOUR));
combination.set(Calendar.AM_PM, targetTime.get(Calendar.AM_PM));
combination.set(Calendar.MINUTE, targetTime.get(Calendar.MINUTE));
combination.set(Calendar.SECOND, targetTime.get(Calendar.SECOND));
combination.set(Calendar.MILLISECOND, targetTime.get(Calendar.MILLISECOND));
final long timeAtCombined = combination.getTimeInMillis();
final SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSSZ");
sdf.setTimeZone(TimeZone.getTimeZone("US/Eastern"));
// subtract one minute
System.out.println(sdf.format(combination.getTime()));
combination.add(Calendar.MILLISECOND, -1);
System.out.println(sdf.format(combination.getTime()));
// millis # 3
System.out.println(sdf.format(new Date(timeAtCombined)));
// millis # 3 - 1ms
System.out.println(sdf.format(new Date(timeAtCombined - 1)));
Output
03/10/2013 03:00:00.000-0400
03/10/2013 01:59:59.999-0500
03/10/2013 03:00:00.000-0400
03/10/2013 01:59:59.999-0500
You're setting everything, except for the time zone (which contains the DST). Set that as well, and you should be okay.
This isn't really an answer to your question directly but you can avoid all of this craziness by going with Joda Time
They have really nailed the date/time/calendar thing down.
i am using the DataType Time in my database it stores the data in the form as 01:23:14.0000000.
i am using dateTime controls of sWt as
DateTime dateTime = new DateTime(cmpGrid, SWT.BORDER | SWT.TIME);
i can save the Value of DateTime easily as
String hours =String.valueOf(timeTo.getHours());
String minutes =String.valueOf(timeTo.getMinutes());
String seconds =String.valueOf(timeTo.getSeconds());
objhallModel.setClose_time(hours + ":"+minutes + ":" + seconds);
For Editting purpose i need to set The time value in my design view For that i want to use
dateTime.setTime(hours, minutes, seconds);
it takes all hours, minutes, second in integer... can please anybody tell me how to set The time in DateTime of Database time value. thanks in advance
I think you are using org.eclipse.swt.widgets.DateTime in your user interface and java.sql.Time to store in your database.
I note that the javadoc of Time says:
The date components should be set to
the "zero epoch" value of January 1,
1970 and should not be accessed.
Therefore, I think you should set it as follows:
DateTime dateTime; // you have this already
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(0); // set to zero epoch
calendar.set(Calendar.HOUR, dateTime.getHours());
calendar.set(Calendar.MINUTE, dateTime.getMinutes());
calendar.set(Calendar.SECOND, dateTime.getSeconds());
Time time = new Time(calendar.getTimeInMillis());
The reverse operation (maybe this is what you want, I wasn't sure from your question) would be:
Time time; // you have this from your Database query
DateTime dateTime; // you have this already or will create a new one
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(time.getTime());
dateTime.setTime(calendar.get(Calendar.HOUR), calendar.get(Calendar.MINUTE),calendar.get(Calendar.SECOND));
First get the date from the database - Date date = resultset.getDate(int) or resultset.getDate(String), then
String hr = String.valorOf(date.getHours());
String min = String.valorOf(date.getMinutes());
String sec = String.valorOf(date.getSeconds());
Now you have the hour, minutes and the seconds.