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.
Related
I have written below code which is running, and giving output. But I'm not sure It's a right one.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = new Date();
sdf.setTimeZone(TimeZone.getTimeZone("GMT-7"));
String value = sdf.format(date);
System.out.println(value);
Date date2 = sdf.parse(value);
long result = date2.getTime();
System.out.println(result);
return result;
The above code what I'm trying is, I just need to get the current time of GMT time zone and convert it as epoch format which is gonna used in Oracle db.
Can someone tell me that format, and the above code is right?
First, you should not store time since the epoch as a timestamp in your database. Look into the date-time datatypes that your DMBS offers. In Oracle I think that a date column will be OK. For most other DBMS you would need a datetime column. timestamp and timestamp with timezone may be other and possibly even sounder options depending on your exact requirements.
However, taking your word for it: Getting the number of milliseconds since the epoch is simple when you know how:
long millisecondsSinceEpoch = System.currentTimeMillis();
System.out.println(millisecondsSinceEpoch);
This just printed:
1533458641714
The epoch is defined in UTC, so in this case we need to concern ourselves with no other time zones.
If you needed seconds rather than milliseconds, it’s tempting to divide by 1000. However, doing your own time conversions is a bad habit since the libraries already offers them, and using the appropriate library methods gives clearer, more explanatory and less error-prone code:
long secondsSinceEpoch = Instant.now().getEpochSecond();
System.out.println(secondsSinceEpoch);
1533458641
You said:
I just need to get the current time of GMT time zone…
Again taking your word:
OffsetDateTime currentTimeInUtc = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println(currentTimeInUtc);
long millisecondsSinceEpoch = currentTimeInUtc.toInstant().toEpochMilli();
System.out.println(millisecondsSinceEpoch);
2018-08-05T08:44:01.719265Z
1533458641719
I know that GMT and UTC are not exactly the same, but for most applications they can be (and are) used interchangeably.
Can someone tell me (if) the above code is right?
When I ran your code just now, its output agreed with mine except the milliseconds were rounded down to whole thousands (whole seconds):
1533458641000
Your code has some issues, though:
You are using the old, long out-dated and poorly designed classes SimpleDateFormat, Date and TimeZone. The first in particular has a reputation for being troublesome. Instead we should use java.time, the modern Java date and time API.
Bug: In your format pattern string you are using lowercase hh for hour of day. hh is for hour within AM or PM, from 1 through 12, so will give you incorrect results at least half of the day. Uppercase HH is for hour of day.
Don’t use GMT-7 as a time zone. Use for example America/Los_Angeles. Of course select the time zone that makes sense for your situation. Edit: You said:
I just want to specify the timezone for sanjose. GMT-7 is refer to
sanjose current time.
I believe many places are called San Jose. If you mean San Jose, California, USA, you are going to modify your program to use GMT-8 every time California goes back to standard time and opposite when summer time (DST) begins?? Miserable idea. Use America/Los_Angeles and your program will work all year.
Since you ask for time in the GMT time zone, what are you using GMT-7 for at all?
There is no point that I can see in formatting your Date into a string and parsing it back. Even if you did it correctly, the only result you would get would be to lose your milliseconds since there are no milliseconds in your format (it only has second precision; this also explained the rounding down I observed).
Links
Oracle tutorial: Date Time explaining how to use java.time, the modern Java date and time API.
San Jose, California on Wikipedia
Why not use Calendar class?
public long getEpochTime(){
return Calendar.getInstance(TimeZone.getTimeZone("GMT-7")).getTime().getTime()/1000; //( milliseconds to seconds)
}
It'll return the current Date's Epoch/Unix Timestamp.
Based on Harald's Comment:
public static long getEpochTime(){
return Clock.system(TimeZone.getTimeZone("GMT-7").toZoneId() ).millis()/1000;
}
Here is a solution using the java.time API
ZonedDateTime zdt = LocalDateTime.now().atZone(ZoneId.of("GMT-7"));
long millis = zdt.toInstant().toEpochMilli();
I've been trying to read the binary file with Java, and the binary file is written in C#. And some of those data is contain a DateTime data.
When DateTime data will be written into the file (in binary), it using DateTime.ToBinary(); on C#.
For reading the DateTime data, it will convert first from bytes into long data, using BitConverter.ToInt64(byte[], 0), and then convert it again from long into DateTime data using DateTime.FromBinary(long). (All of those are written in C#).
Let's say the long data after converting from bytes is = -8586803256090942249, and when convert it into DateTime, it will return = 3/17/2018 5:07:56 PM
Now, I'm trying to read that binary file with Java. And for converting the bytes data into long data, I'm using this code : ByteBuffer.wrap(byte[]).order(ByteOrder.LITTLE_ENDIAN).getLong().
It will return the exact long data value as C# did. But when I try to convert it from long data into DateTime in Java, using Date date = new Date(long), it will return = Sun May 06 19:04:17 WIB 272097407 instead.
Can you help me what is the correct solution for this ? Is there any equivalent for DateTime.FromBinary() from C# in Java ? Or is my code wrong ? All of yours answers is really appreciated.
In Java:
long fromBytes = -8586803256090942249L;
// Mask out kind and ticks
int kind = Math.toIntExact((fromBytes >> 62) & 0x3);
long ticks = fromBytes & 0x3FFF_FFFF_FFFF_FFFFL;
LocalDateTime cSharpEpoch = LocalDate.of(1, Month.JANUARY, 1).atStartOfDay();
// 100 nanosecond units or 10^-7 seconds
final int unitsPerSecond = 10_000_000;
long seconds = ticks / unitsPerSecond;
long nanos = (ticks % unitsPerSecond) * 100;
LocalDateTime ldt = cSharpEpoch.plusSeconds(seconds).plusNanos(nanos);
switch (kind) {
case 0: // Unspecified
case 2: // Local time
System.out.println("Result LocalDateTime: " + ldt);
break;
case 1: // UTC
OffsetDateTime utcDateTime = ldt.atOffset(ZoneOffset.UTC);
System.out.println("Result OffsetDateTime in UTC: " + utcDateTime);
break;
default:
System.out.println("Not a valid DateTimeKind: " + kind);
break;
}
Output:
Result LocalDateTime: 2018-03-17T10:07:56.383355900
Edit: The number is
A 64-bit signed integer that encodes the Kind property in a 2-bit
field and the Ticks property in a 62-bit field.
Tetsuya Yamamoto was correct so far as the ticks property denotes number of 100-nanosecond intervals elapsed since 0001/01/01 at start of day (midnight). The kind is either 0 for unspecified, 1 for UTC or 2 for local time. So I am masking the kind and the ticks out separately.
Even though the kind is 2 in your case, which should be for local time, it seems that the time is indeed in UTC. It’s the only way that the time printed could agree with your expected 5:07:56 PM Western Indonesian Time. Maybe the number was generated on a computer with its time zone set to UTC.
To get the time in your time zone:
ZoneId targetZone = ZoneId.of("Asia/Jakarta");
ZonedDateTime zdt = ldt.atZone(ZoneOffset.UTC).withZoneSameInstant(targetZone);
System.out.println("Converted to target time zone: " + zdt);
Converted to target time zone: 2018-03-17T17:07:56.383355900+07:00[Asia/Jakarta]
This agrees with what you said you got on the C# side.
PS Avoid the Date class in Java if you can, it is long outdated and poorly designed and was replaced many years ago now by java.time, the modern Java date and time API (which I am of course using in the above). If you do need a Date for a legacy API that you cannot change or don’t want to change just now, as you already noted in a comment, the conversion is like this:
Instant inst = ldt.atOffset(ZoneOffset.UTC).toInstant();
Date date = Date.from(inst);
System.out.println(date);
Output on a JVM with default time zone Asia/Jakarta:
Sat Mar 17 17:07:56 WIB 2018
Acknowledgement: Andreas in an answer (link below) explained the structure of the 64 bits number and gave the link to the documentation. I have taken them from there.
Links
DateTime.FromBinary(Int64) Method from the .NET documentation
Andreas’ answer to a duplicate question
I want to calculate the number of days from the "beginning of time" to a current date. This could be easily achieved with a simple calculation (timestamp / 24 / 60 / 60 / 1000 = daysFromBeginningOfTime) but the twist is that i need to be aware of time zones as well. The timestamp is the same everywhere in the world but when you parse it with the proper time zone then it reflects the differences between locations so using just the timestamp doesn't work and i don't want to handle all the time zone transitions myself.
Example:
if it's 23:30 in London and the day number is 18843 then in Amsterdam it's 0:30 and the day number should be 18844.
I looked at joda.time but didn't really find what i was looking for.
Anyone have any ideas?
The problem appears due to a wrong initial assumption, I think.
The argument the OP makes in his example is not correct. No matter what the clock shows in London or Amsterdam, the time difference to the start of the epoch is - at every point of time - independent of where you are in the world.
Hence, the solution is to parse a given input date to an UTC timestamp and proceed as before.
(Ignoring the point that zero is not "the beginning of time" ... and that the actual time point for the beginning of time is probably unknowable ...)
Here's how to calculate the number of days since "the local-time UNIX epoch in a given timezone"1.
Get hold of the object that represents the local timezone.
Get the timezone's offset from the object
Convert it to milliseconds and add it to the current UTC time.
Calculate the day number as before.
1 - ... whatever that means.
I have String with the format "\/Date(1339638938087-0500)\/" from a web service api.
Using java, how can I put this into a org.joda.time.DateTime variable?
You need to extract these two bits of information:
-2208967200000: milliseconds since the unix epoch (January 1st 1970 UTC)
-0600: offset from UTC
This assumes that the example represents January 1st 1900 at midnight local time - as the -2208967200000 part represents 6am UTC.
To convert this into a Joda Time DateTime, you should extract the two parts (get rid of everything outside the brackets, and then either use the length to split it, or find the middle +/- symbol).
Next, parse the first part as a long for the millis section.
Then, parse the second part - probably as hours, minutes and sign separately. (I'm assuming it's always in the form xHHmm where x is the sign, HH is the minutes as two digits, and mm is the hours as two digits.)
Create a fixed time zone for the offset using DateTimeZone.forHoursMinutesOffset or something similar.
Finally, create the time with
new DateTime(millis, zone);
Oh, and then kick whoever's producing such a horrible format...
this look like unix timestamp
The unix time stamp is a way to track time as a running total of
seconds. This count starts at the Unix Epoch on January 1st, 1970
If the "2208967200000" is a time in milliseconds since January 1, 1970, 00:00:00, you can use it in constructor for Date(time);
String dateStr="Date(-2208967200000-0600)";
String timeInMillis=dateStr.Split("-")[1];
String utcStr=dateStr.Split("-")[2].Substring(0,4);
Date d=new Date(Long.parseLong(timeInMillis));
if you want you can handle utcStr if it is necessary (if the second part after "-" is a time zone)
I need to convert some epoch time stamps to the real date and have used some of the methods I found on stack overflow, but they give the wrong answer.
As an example, one date is "129732384262470907" in epoch time, which is "Mon, 20 Jan 6081 05:24:22 GMT" using http://www.epochconverter.com/
However, my code generates: "Wed Dec 24 14:54:05 CST 19179225"
String epochString = token.substring(0, comma);
long epoch = Long.parseLong(epochString);
Date logdate = new Date(epoch * 1000);
BufferedWriter timewrite = new BufferedWriter(new FileWriter(tempfile, true));
timewrite.write(logdate);
timewrite.flush();
timewrite.close();
The initial timestamp is in miliseconds, which in the examples I saw here I am supposed to multiply by 1000.
If I don't multiply by 1000, I get: "Mon Aug 08 01:14:30 CDT 4113025"
Both of which are wrong.
So where have I made my error?
129732384262470907 is actually in microseconds since the epoch if it's meant to be 6081, so you need to divide by 1000 if that's real input.
Note that epochconverter.com doesn't even handle that value - it only allows you to enter 129732384262470 which it then treats as milliseconds since the epoch.
You need to multiply by 1000 if your data is seconds since the epoch. Basically all you need to know is that Java expects milliseconds since the epoch; the rest should be plain sailing, assuming you know what your input data actually means.
If you could provide your real data, and what it's meant to represent, it's probably going to be easy to fix your problems.
If you look carefully, epochconverter.com truncated that number because it was too long for the entry field.
I suggest you print the current value of System.currentMillis() to see what approximate range a "current" epoch-based timestamp has, and re-scale your input number to match. I think you'll probably have to divide by 1000.
In fact, looking closer, if you divide by 10,000, you get 1297323842624, which comes out to a date in 2011. So it's not at all clear what units the number you've given are in.