localTimeDate formula conversion - java

I came across following formula in which localTimeDay is being retrieved from TimeStamp and Timezone:
long localTimeDay = (timeStamp + timeZone) / (24 * 60 * 60 * 1000) * (24 * 60 * 60 * 1000);
I am not able to understand what is the meaning of Local Time Day and how this formula "magically" converts based on TS and TZ.

timestamp is a count of milliseconds since the epoch of Jan 1, 1970 at 00:00 UTC.
timeZone is the offset in milliseconds from UTC. It may be positive, negative or zero. It must have its sign reversed, though, for the formula to work, as far as I can see: an offset of +01:00 should be given as minus 3 600 000 milliseconds. When I add the offset, I get a different point in time where the date and time of day in UTC is the same as the original date and time of day at that UTC offset.
Dividing by 24 * 60 * 60 * 1000 converts from milliseconds to days since the epoch. Any fraction of a day, that is, any time of the day, is discarded.
Multiplying by 24 * 60 * 60 * 1000 converts back from days to milliseconds. Since the time of day was discarded, we now have the time at 00:00 UTC on that day.
So it’s a way of converting from a point in time at some UTC offset to the date alone represented in UTC.
It’s not code that you would want to have in your program. You should leave such conversions to proven library methods. It might however be code that could be found inside such a tested and proven library.
Edit: Why do I believe that the sign of the offset has been reversed? Couldn’t it be the opposite conversion, from UTC to local? The variable name localTimeDay seems to suggest this? The division and multiplication only works in UTC. Since the epoch is at 00:00 UTC, the formula necessarily gives you the start of a day in UTC, it cannot give you the start of a day at any non-zero offset. Therefore I figure that the conversion must be from local to UTC.
How to do in your code
Here’s a nice way of doing the same conversion using java.time, the modern Java date and time API
// The point in time given in UTC
Instant time = Instant.parse("2020-04-23T05:16:45Z");
// The UTC offset, +02:00
ZoneOffset offset = ZoneOffset.ofHours(2);
ZonedDateTime startOfDayInUtc = time.atOffset(offset)
.toLocalDate()
.atStartOfDay(ZoneOffset.UTC);
System.out.println(startOfDayInUtc);
long epochMillis = startOfDayInUtc.toInstant().toEpochMilli();
System.out.println(epochMillis);
Output:
2020-04-23T00:00Z
1587600000000
We can check that it gives the same result as your code line:
long timeStamp = time.toEpochMilli();
// Reverse sign of offset
long timeZone = -Duration.ofSeconds(offset.getTotalSeconds()).toMillis();
long localTimeDay = (timeStamp + timeZone) / (24 * 60 * 60 * 1000) * (24 * 60 * 60 * 1000);
System.out.println(localTimeDay);
System.out.println("Agree? " + (localTimeDay == epochMillis));
1587600000000
Agree? true
Edit: you asked in a comment:
I still have this doubt: There is fixed number of millis that have
elapsed since Jan 1 1970, so every country should get same number.
Does localTimeDate mean "date for my country" or to the country where
this data came from? For example: Country-A , Country-B; they will see
same millis since Epoch. Suppose data processing is happening in
Country-A and origin of data is Country-B. So when we say
"localTimeDate" , does it pertain to Country-A or Country-B.
It will work for both countries. It all depends on the timeZone value that enters into the formula. If that is the UTC offset for country A (sign reversed), the conversion will be from country A time to UTC date. If it’s country B’s offset, the conversion will be from country B time. And you are fully correct, you will get two different dates if it’s not the same date in countries A and B, which could easily be the case.

Related

Convert 18 decimal Julian Timestamp with Java

I need to convert what I think is a Julian timestamp to a regular time stamp with Java.
The application that generates this timestamp is a proprietary payment system (Base24-EPS from ACI). I need to be able to pull and parse the value from the database with a Java application.
A sample timestamp value in decimal is 18 digits:
137955731472778910
With DALCI (internal tool provided by Base24-EPS), I can see this is equivalent of:
3: convert 137955731472778910 to datetime(yyyy/mm/dd hh:mm:ss);
2019/12/14 12:39:07
I found an answer here which seems to be related. But 137955731472778910 is smaller than 210866803200000000, which is the Julian timestamp for 01-JAN-1970 (epoch for unix time).
All the other Julian timestamp online converter I see, for example http://www.onlineconversion.com/julian_date.htm, have Julian date format as double 2458806.52903.
18 digits seem too long.
Do you know how can I parse this timestamp format with Java?
Many thanks.
Assuming you are in the UTC timezone (you probably aren't, but you haven't told me what timezone you are in), I have a formula:
long timestampFromAci = ...;
long timestampJava = (timestamp - 122192460002790000L) / 10000;
Instant.ofEpochMilli(timestampJava);
new Date(timestampJava); // Old, deprecated - use java.time classes
This assumes that the conversion is linear.
Your product timestamp has 10000 units per millisecond, since there are 2145052000 milliseconds between 2019/11/19 16:48:15 and 2019/12/14 12:39:07, and the difference in your product's timestamp is 21450514084700.
If you divide these two, that's almost exactly 10000 - the difference is because your tool doesn't display fractional seconds.
Extrapolating from that, I can derive that value that your product timestamp would have for the Unix epoch op 1/1/1970 - 122192460002790000.
However, as I said, I made the assumption that you are in the UTC timezone. For every hour that your timezone is off from UTC, you need to adjust that number by 3600 seconds times 10,000,000 units product timestamp units per second.

Formula For Calculating Difference in Time

I have two times in hours and minutes.
time[0]: hour1
time[1]: minutes1
time[2]: hour2
time[3]: minutes2
I've created this formula to calculate the difference in time in minutes:
((time[2] % 12 - time[0] % 12) * 60) + (time[3] - time[1])
I was wondering if there are any edge cases to this. In addition, what is the paradigm you would follow to create this formula (although it is very basic)?
You could express your times with the Date class instead, then calculate the difference and then express it in the time unit of your choice.
With this method, you will avoid a lot of tricky cases (difference between two times on two different days, time change, etc.).
I recommend you the reading of this post and this post but there are many answers to this same exact question on StackOverflow ;)
Note: before using Date, have a look to this excellent post: What's wrong with Java Date & Time API?
Your code assumes days are 24 hours long. Not all days are 24-hours long. Anomalies such as Daylight Saving Time (DST) mean days vary in length.
Also, we have classes already built for this. No need to roll your own. The LocalTime class represents a time-of-day without a date and without a time zone. A Duration represents a span of time not attached to the timeline.
LocalTime start = LocalTime.of( 8 , 0 ) ;
LocalTime stop = LocalTime.of( 14 , 0 ) ;
Duration d = Duration.between( start , stop );
long minutes = d.toMinutes() ; // Entire duration as a total number of minutes.
That code too pretends that days are 24 hours long.
For realistic spans of time, use the ZonedDateTime class to include a date and time zone along with your time-of-day.

Java: Elegant solution to get a special Date as a long?

Edit:
lets say I have the date 11.11.2016 for what I want the Unix timestamp.
At the moment I just use
final int start = (int) ((System.currentTimeMillis() - 24 * 60 * 60 * 1000 * 5) / 1000L);
for 10.11.2016 it would be
final int start = (int) ((System.currentTimeMillis() - 24 * 60 * 60 * 1000 * 6) / 1000L);
But it looks somehow so basic :)
Is there maybe a better solution? I couldn't find any function in Date nor LocalTime.
Thanks!
It only makes sense to convert a "date" to epoch seconds if you specify a time of day and a time zone that you want the epoch seconds for.
Otherwise, the conversion is undefined, because a "date" is a 24-hour period (usually) in a specific timezone, whereas a unix timestamp is a number of seconds since 1970-1-1 00:00:00 UTC.
LocalDate.of(2016, 5, 10)
// e.g. LocalTime.of(12, 0) or .atStartOfDay()
// - *not* midnight, in general, since this does not always exist.
.atTime(someLocalTime)
// e.g. ZoneId.of("UTC")
.atZone(someTimeZoneId)
.toEpochSecond();

Joda: get local milliseconds of specific timezone

I never would believe that this could amount to being such a hassle. I am trying to make a clock that always displays the local time in specific timezones.
My laptop is currently set in GMT0 timezone (UK).
I want to get the milliseconds of the timezone "Europe/Stockholm".
So let's say it's 17:00 here in the UK I would like to get the milliseconds corresponding to 18:00 which would be the Swedish time.
The time in milliseconds as used by Date is independent of the time zone. Only when you print (or parse) a time, you use a DateFormat that is localized, so it ensures you get the time in the specific timezone.
When time is represented as milliseconds (or seconds or nanoseconds, etc), that is almost always milliseconds since some epoch. In the case of unix and java, this is midnight Jan 1, 1970 UTC.
Time zones are generally arranged as a round number of hours relative to UTC. In certain time zones it's not a round hour but 30 minutes, 15 minutes or 45 minutes from a round hour.
Nevertheless, for any time unit below a minute, all those time zones match UTC exactly.
Therefore, whatever the current second or millisecond is in Sweden, it is the same as it is, for example, in Nepal, whose time zone is 5:45 minutes from UTC.
When you work with an object that allows you to retrieve the separate fields of the given time, the milliseconds field will usually reflect just the number of milliseconds since the beginning of the current second, not the number of milliseconds since midnight. Therefore it will never be more than 999, and it will be the same the world over.
After reading the answers here and discovering another route, this is what finally worked for me.
DateTime curDateTime = new DateTime();
int offset = DateTimeZone.forID("Europe/Stockholm").getOffset(curDateTime.getMillis());
long milli = (curDateTime.getMillis()+offset);

How to define the date format?

I have the int number 2455449 and I know that represents the date 09/09/2010. How can I define the date format wihch is used? I need to generate a new date in this format. It will be used for http requests. I suppose that is Julian but I'm not sure. I tried to convert this number to the date but it didn't return the right date of 09/09/2010. Probably I used a wrong SimpleDateFormat("mm/dd/yy") or Calendar.XXXX (e.g.Calendar.DAY_OF_YEAR)
var now = new Date();
now.format("m/dd/yy");
// Returns, e.g., 6/09/07
// Can also be used as a standalone function
dateFormat(now, "dddd, mmmm dS, yyyy, h:MM:ss TT");
// Saturday, June 9th, 2007, 5:46:21 PM
// You can use one of several named masks
now.format("isoDateTime");
// 2007-06-09T17:46:21
// ...Or add your own
dateFormat.masks.hammerTime = 'HH:MM! "Can\'t touch this!"';
now.format("hammerTime");
// 17:46! Can't touch this!
http://blog.stevenlevithan.com/archives/date-time-format
looks like an equation with unknown function.f(d,m,y)=D; Where d the day, m month,y year and D is int date. And without loss of generality we can assume that this mapping should be one to one i.e. every valid (d,m,y) combination should map to a unique positive integer (>=0) and every positive integer must represent a valid and unique (d,m,y) tuple.So the most obvious choice of function f (based on the property of dates) is number of days elapsed since the first day, which satisfies our conditions. so now we have boundary condition.f(d1,m1,y1)=0;
f(9,9,2010)= 2455449;where d1,m1,y1 represents the reference date like epoch in unix timestamp. Using the obvious function (see above), (d1,m1,y1) comes out to be (10 5 -4713). So the DatFormat used is number of days elapsed since 10th June 4713 B.C. Approximately.
It is a Julian day number, and it counts the number of days since January 1, 4713 BC Greenwich noon in the Julian proleptic calendar.
To convert from a JD to a unix time stamp:
unix_time_stamp = ( JD -2440587.5) * 86400
To convert from unix time stamp to JD:
JD = (unix_time_stamp / 86400) + 2440587.5
Note that JD is counted from the noon, not midnight. That's why it's .5 at the end of the addition.
Update If you want to use it in javascript (that uses milliseconds since the epoch)
function dateFromJulianDay(julian_day) {
return new Date( (julian_day - 2440587.5) * 86400000);
}
function dateToJulianDay(date) {
// date should be a javascript Date object
// or a variable with milliseconds since the unix epoch 1 jan 1970
return ( date / 86400000) + 2440587.5;
}
console.log(dateFromJulianDay(2455449));
console.log(dateToJulianDay(new Date(2010,9-1,9)));
Remember that the month in the Date constructor is 0-11, whats why I do -1 above.

Categories

Resources