converting timestamp date to unix timestamp - java

i have data like this one
date what i got from timestamp utc are : 2020-06-29 05:31:58.153
LocalDateTime timestampasstring = message.getHeader().getUtcTimeStamp( SendingTime.FIELD);
Timestamp timestamp = Timestamp.from(timestampasstring.toInstant(ZoneOffset.UTC));
System.out.println(timestamp);
String timestampstrings = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp);
String timestampstrings2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(timestamp);
i need to get timestamp number like 2020-06-29 05:31:58
and convert it become unix timestamp like this one 1593408718
how to convert it ?

If your getUtcTimeStamp method is helpful enough to return a LocalDateTime, you're most of the way there. Convert to an Instant using ldt.atOffset(ZoneOffset.UTC) (your getUtcTimeStamp really should be doing this for you if it already knows it's in UTC), then just call toEpochSecond() (or toEpochMilli() if you want the milliseconds part, but you just showed whole seconds).

Having read your question, I assume your method message.getHeader().getUtcTimeStamp(SendingTime.FIELD) returns a String (not a LocalDateTime) representing a timestamp in UTC while being formatted either like 2020-06-29 05:31:58.153 or 2020-06-29 05:31:58.
Since you have (shown) differently formatted datetimes (respectively, datetimes with a different accuracy), you will have to take care of that by defining a suitable DateTimeFormatter using a pattern able to deal with optional milliseconds (yyyy-MM-dd HH:mm:ss[.SSS]).
You can use it as follows:
public static void main(String[] args) {
// receive the result from your message, this is just an example
String utcTimestamp = "2020-06-29 05:31:58";
// create a ZonedDateTime by parsing the String to a LocalDateTime and adding a time zone
ZonedDateTime zdt = LocalDateTime.parse(utcTimestamp,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]"))
.atZone(ZoneId.of("UTC"));
// then get the epoch milliseconds / unix timestamp
long millis = zdt.toInstant().toEpochMilli();
// and print the result
System.out.println(zdt + " ==> " + millis + " epoch millis");
}
The output of this is, of course, different for datetimes that are only equal down to seconds:
2020-06-29T05:31:58Z[UTC] ==> 1593408718000 epoch millis
2020-06-29T05:31:58.153Z[UTC] ==> 1593408718153 epoch millis
If you call long seconds = zdt.toEpochSeconds() instead of converting toInstant().toEpochMillis (and adjust the output a little) you will get the same value for both examples:
public static void main(String[] args) {
// receive the result from your message, this is just an example
String utcTimestamp = "2020-06-29 05:31:58.153";
// create a ZonedDateTime by parsing the String to a LocalDateTime and adding a time zone
ZonedDateTime zdt = LocalDateTime.parse(utcTimestamp,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]"))
.atZone(ZoneId.of("UTC"));
// then get the epoch seconds
long seconds = zdt.toEpochSecond();
// and print the result
System.out.println(zdt + "\t==>\t" + seconds + " epoch seconds");
}
Output:
2020-06-29T05:31:58Z[UTC] ==> 1593408718 epoch seconds
2020-06-29T05:31:58.153Z[UTC] ==> 1593408718 epoch seconds
If your method really returns a LocalDateTime, you could simply skip conversions and write
public static void main(String[] args) {
LocalDateTime utcDateTime = message.getHeader().getUtcTimeStamp(SendingTime.FIELD);
// then get the epoch seconds
long seconds = utcDateTime.atZone(ZoneId.of("UTC")).toEpochSecond();
// and print the result
System.out.println(utcDateTime + "\t==>\t" + seconds + " epoch seconds");
}

The other answers are fine. Here’s my variant. First declare a formatter for parsing:
private DateTimeFormatter timestampFormatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter();
Consider declaring the formatter static and/or final. With this formatter I’d do:
String timestampAsString = "2020-06-29 05:31:58.153";
OffsetDateTime dateTime = LocalDateTime
.parse(timestampAsString, timestampFormatter)
.atOffset(ZoneOffset.UTC);
long unixTimestamp = dateTime.toEpochSecond();
System.out.println(unixTimestamp);
Output is what you asked for:
1593408718
The nice thing about the formatter is that it accepts both 2020-06-29 05:31:58.153 and 2020-06-29 05:31:58, that is, time both with and without fraction of second, and with any fraction of from 1 up to 9 decimals. Reusing ISO_LOCAL_TIME in the formatter buys us this.

Related

How to adjust a Timestamp that comes from my database?

In the database, a time is saved as a Timestamp in the UTC time zone (that is, 0). When I get it, I need to add the Timezone from the place that I will send. I have these two pieces of information, but I can't find the time.
This is the code from which I get both information. I've tried to transform to LocalDateTime and adjust the zone, but it didn't produce any results. There is no much of code:
Timestamp timestamp = resultQueryCamerasOffline.getLastOnline();
String zoneId = resultQueryCamerasOffline.getEmpresaTimezone();
System.out.println(timestamp.toString());
System.out.println(zoneId);
2020-03-12 03:01:45.0
America/São_Paulo
In the database, last_online has value:
2020-03-12 03:01:45.0
You can and maybe have to use a LocalDateTime in order to achieve what you want, but the final product should be a ZonedDateTime.
Basically, the timestamp should be converted to a LocalDateTime and that LocalDateTime can then be converted to a ZonedDateTime by adding a specific ZoneId, like this:
Just adding a zone, leaving the datetime as is:
public static void main(String[] args) {
// get or take a timestamp
java.sql.Timestamp timestamp = Timestamp.valueOf("2020-03-12 03:01:45.0");
// transforming it into a LocalDateTime
LocalDateTime localDateTime = timestamp.toLocalDateTime();
// now create a ZonedDateTime by putting a zone
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime,
ZoneId.of("America/Sao_Paulo"));
// and print the result
System.out.println(zonedDateTime);
}
The output is
2020-03-12T03:01:45-03:00[America/Sao_Paulo]
If you are sure the client that runs this code always has the desired time zone, then you can alternatively use ZoneId.systemDefault() when the ZonedDateTime is being created.
But if you don't just want to add a zone but really convert the Instant to another zone, then you can do this:
Converting the Instant to another time zone:
public static void main(String[] args) {
// get or take a timestamp
java.sql.Timestamp timestamp = Timestamp.valueOf("2020-03-12 03:01:45.0");
// transforming it into a LocalDateTime
LocalDateTime localDateTime = timestamp.toLocalDateTime();
// now create a ZonedDateTime by putting a zone
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(
localDateTime.toInstant(ZoneOffset.of("+00:00")),
ZoneId.of("America/Sao_Paulo"));
// and print the result
System.out.println(zonedDateTime);
}
This outputs
2020-03-12T00:01:45-03:00[America/Sao_Paulo]
You can have the second one shorter:
public static void main(String[] args) {
// get or take a timestamp
java.sql.Timestamp timestamp = Timestamp.valueOf("2020-03-12 03:01:45.0");
// transforming it into a LocalDateTime
ZonedDateTime utc = ZonedDateTime.of(timestamp.toLocalDateTime(), ZoneId.of("UTC"));
// now create a ZonedDateTime by putting a zone
ZonedDateTime saoPaulo = utc.withZoneSameInstant(ZoneId.of("America/Sao_Paulo"));
// and print the result
System.out.println(saoPaulo);
}
The output stays
2020-03-12T00:01:45-03:00[America/Sao_Paulo]
If you want the output formatted differently, you have to either choose one of the built-in patterns (public constants of DateTimeFormatter, like DateTimeFormatter.ISO_ZONED_DATE_TIME) or give it a custom one (by DateTimeFormatter.ofPattern(String pattern) plus an optional Locale):
public static void main(String[] args) {
// get or take a timestamp
java.sql.Timestamp timestamp = Timestamp.valueOf("2020-03-12 03:01:45.0");
// transforming it into a LocalDateTime
ZonedDateTime utc = ZonedDateTime.of(timestamp.toLocalDateTime(), ZoneId.of("UTC"));
// now create a ZonedDateTime by putting a zone
ZonedDateTime saoPaulo = utc.withZoneSameInstant(ZoneId.of("America/Sao_Paulo"));
// create a formatter for your locale and with the desired pattern
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEEE dd MMM yyyy hh:mm:ss a xxx",
Locale.forLanguageTag("pt-BR"));
// and print the result
System.out.println(saoPaulo.format(dtf));
}
This time, the output is formatted in a totally different way:
Quinta-feira 12 mar 2020 12:01:45 AM -03:00
get the millis from your timestamp and try:
LocalDateTime date = LocalDateTime
.ofInstant(Instant.ofEpochMilli(timestamp.getTime()), ZoneId.systemDefault(yourTimezone()));
or try using a ZonedDateTime

Date and time to UTC given timezone

i have the following string: 2019120610000100 which corresponds to 2019/12/06 at 10:00 +1.
How can I convert this to utc time, in this case 2019/12/06 09:00?
This string could also have a +2, +3 ... -1, -2 ... timezone so I must be able to convert other strings too.
The + or - sign is given in another instance however, if it can be useful, it can be added to the time and date string.
(The string could become 201912061000 +0100)
Right now I'm converting it manually splitting the string but I'm trying to find a way to make this safe as it gets tricky with hours and minutes like 00 that have to change the day, possibly the month and year.
This is what I have made so far:
hour -= hourOffset;
if(hour<0){
hour += 24
}
minutes -= minutesOffset;
if(minutes<0){
minutes += 60
}
When dealing with dates and times, it is usually better to not do string operations but use one of the many classes that extend java.time.temporal.Temporal from the java.time package - introduced with Java 8.
In your case, you want to use an OffsetDateTime, as your string represents exactly that: A date-time with an offset. Note, that a ZonedDateTime is not really appropriate here, because the offset information (e.g. "+01:00") is not enough to represent a whole timezone. Look at this SO question for more information.
To get an OffsetDateTime from a string, you must simply parse it.
Let's do it.
Step 1: Adjust your string to contain the offset sign (plus or minus).
String offsetSign = "+";
String datetimeString = "2019120610000100";
datetimeString = new StringBuilder(datetimeString).insert(datetimeString.length() - 4, offsetSign).toString();
Step 2: Parse that string to an OffsetDateTime object.
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmZ");
OffsetDateTime odt = OffsetDateTime.parse(datetimeString, dtf);
Step 3: Convert that OffsetDateTime to UTC.
OffsetDateTime odtUTC = odt.withOffsetSameInstant(ZoneOffset.UTC);
Printing out those variables
System.out.println(datetimeString);
System.out.println(odt);
System.out.println(odtUTC);
will get you the following output:
201912061000+0100
2019-12-06T10:00+01:00
2019-12-06T09:00Z
You can directly convert the time to UTC by the following code
String dateStr = "201912061000+0100";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
final LocalDateTime parse = LocalDateTime.parse(dateStr.substring(0, dateStr.length()-5), formatter);
final ZoneId zone = ZoneId.of("GMT"+dateStr.substring(12,15)+":"+dateStr.substring(15));
final ZonedDateTime given = ZonedDateTime.of(parse, zone);
final String toUTC = given.withZoneSameInstant(ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"));
String dateStr = "2019120610000100";
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("yyyyMMddHHmm Z");
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("yyyy/MM/dd hh:mm");
String adjustedDateStr = new StringBuilder(dateStr).insert(dateStr.length() - 4, " +").toString();
ZonedDateTime givenDate = ZonedDateTime.parse(adjustedDateStr, dtfInput);
ZonedDateTime timezoneAdjustedDate = ZonedDateTime.ofInstant(givenDate.toInstant(), ZoneId.of("UTC"));
System.out.println(dtfOutput.format(timezoneAdjustedDate));
Since you handle the plus or minus for the timezone offset externally, you can just insert it into the exsample above instead of the plus if need be.

trying to convert timestamp to time with data type as int

Trying to convert timestamp to time with any zone using java, here I'm able to convert using ZoneID but it will return string data type. here I'm expecting output like getTimeMillis()
Instant now = Instant.ofEpochMilli(lngDate);
ZoneId zoneId = ZoneId.of("America/Chicago");
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(now, zoneId);
DateTimeFormatter isoDateFormatter = DateTimeFormatter.ISO_DATE_TIME;
String zdt = zonedDateTime.format(isoDateFormatter);
Here I'm expecting only time millis (8-digits number) and below giving you my code can you please help to solve it.
Input : 1552979609000L
DateTimeFormatter isoDateFormatter = DateTimeFormatter.ISO_TIME;
String zdt = zonedDateTime.format(isoDateFormatter); // output in string : 00:13:29-07:00
LocalTime time = LocalTime.parse(zdt, isoDateFormatter); // output in local time : 00:13:29
If I understand correctly, you want the millisecond of the day, in other words, the count of milliseconds since 00:00:00 as in int from 0 (inclusive) to 86 400 000 (exclusive; up to 8 digits). The ChronoField enum has a constant for that, so it’s straightforward when you know how:
int millisecondOfDay = zonedDateTime.get(ChronoField.MILLI_OF_DAY);
System.out.println("Millisecond of day: " + millisecondOfDay);
Output when running just now:
Millisecond of day: 7773854

switch between ofEpochMilli and ofEpochSecond

In my application one of third party API returning timestamp in epoch.
Sometime it returns epoch time in seconds and sometime in miliseconds not confirmed. My application using below code to
convert it to java date and display to user but when I am receiving time in miliseconds it is failing on year.
String time = "1519377196185"; //Time in miliseconds
//String time = "1521575819"; //Time in seconds.
String timeZone = "US/Pacific";
long epochdate = Long.parseLong(time);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd, yyyy hh:mm a");
LocalDateTime date34 =
Instant.ofEpochSecond(epochdate)
.atZone(ZoneId.of(timeZone))
.toLocalDateTime();
String date = date34.format(formatter).toString();
System.out.println("date : " + date);
if I use Instant.ofEpochMilli(epochdate) for miliseconds then it is working fine. So my question is how I can know that coming timestamp is in miliseconds or seconds so on that basis I will switch between ofEpochMilli and ofEpochSecond
Year Offset
I would try to parse first the date as seconds, given that if the date is in millis the year would be something extremely big (in this case 50000), then if the year is not greater than the year defined offset (e.g. 3000), that date is returned, otherwise the date is returned as millis.
public ZonedDateTime getZonedDateTime(String time) {
long longTime = Long.parseLong(time), yearOffset = 3000L;
String timeZone = "US/Pacific";
ZoneId zoneId = ZoneId.of(timeZone);
ZonedDateTime zdt = Instant.ofEpochSecond(longTime).atZone(zoneId);
if (zdt.getLong(ChronoField.YEAR_OF_ERA) >= yearOffset) {
return Instant.ofEpochMilli(longTime).atZone(zoneId);
} else {
return zdt;
}
}
Using the functions prints:
getZonedDateTime("1519377196185"); // 2018-02-23T01:13:16.185-08:00[US/Pacific]
getZonedDateTime("1521575819"); // 2018-03-20T12:56:59-07:00[US/Pacific]
Margin of Error
Any method that you decide to use, would have the possibility of an error and that the date is transformed incorrectly, specially when the date is in milliseconds and is too close of the epoch 1970-01-01T00:00:00Z.
The margin errors using the year offset of 3000 would be:
When the date is originally in milliseconds in the range from 1970-01-01T00:00:00Z until 1971-01-12T04:48:00Z
Would be considered as date in seconds
When the date is originally in seconds and the date is equal or after 3000-01-01T00:00:00Z (improbable date in normal apps)
Would be considered as date in milliseconds
Calculate the range of error in milliseconds dates
You can calculate the range of error for dates originally in milliseconds with:
Instant.ofEpochMilli(LocalDateTime.of(3000, 1, 1, 0, 0) // year = 3000
.toEpochSecond(ZoneOffset.UTC)); // 1971-01-12T04:48:00Z
One easy (temporary, sort of) solution would be to just check the length of your time String. If the length is equal to 13, then it represents milliseconds. This will be true until 1 ms after 2286-11-20T17:46:39.999Z, which is a long time from now. The time in seconds would take even more time to reach a length of 13.
Inspect length of String input
As stated by Jacob G. his Answer, check the length.
String input = "1519377196185"; // Milliseconds since epoch.
//String input = "1519377196" ; // Seconds since epoch.
Instant instant = null;
int length = input.length();
switch ( length )
{
case 13:
instant = Instant.ofEpochMilli( Long.parseLong( input ) );
break;
case 10:
instant = Instant.ofEpochSecond( Long.parseLong( input ) );
break;
default:
throw new IllegalStateException( "Unexpected length of input text for count-from-epoch number: " + input + ". Message # 2188d054-5720-4393-9b18-829913d7ba1c." );
}
System.out.println( input + " ➞ " + instant.toString() ); // Generate a String representing textually the value of the `Instant` object.
1519377196185 ➞ 2018-02-23T09:13:16.185Z
Or:
1519377196 ➞ 2018-02-23T09:13:16Z
ZonedDateTime
To move from UTC in an Instant to some particular time zone, provide the context of a time zone (ZoneId) to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2018-02-23T10:13:16.185+01:00[Africa/Tunis]
LocalDateTime - not appropriate here
The LocalDateTime class is the wrong class to use, as seen in the Question. This class purposely lacks any concept of time zone or offset-from-UTC. So it does not represent a moment, and is not a point on the timeline. This class represents potential moments along a range of about 26-27 hours.
Use LocalDateTime only when the zone/offset is unknown (a terrible situation) or when you need an indefinite value such as “Christmas starts on first moment of December 25, 2018”.
You can solve this other way by converting epoch in seconds to epoch in milliseconds and apply only Instant.ofEpochMilli() for both:
String time = "1519377196185"; //Time in miliseconds or seconds
if(time.length() == 10) { // length of epoch in seconds is 10
time = time + "000";
}
String timeZone = "US/Pacific";
long epochdate = Long.parseLong(time);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd, yyyy hh:mm a");
LocalDateTime date34 = Instant.ofEpochMilli(time)
.atZone(ZoneId.of(timeZone))
.toLocalDateTime();
String date = date34.format(formatter).toString();
System.out.println("date: " + date);

Java get UTC time

I want to get the time in UTC time zone. So I wrote the code:
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;
public class RegularSandbox {
public static void main(String[] args) {
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println("DATETIME = " + Date.from(utc.toInstant()));
}
}
The problem is the output shows me the time in PST (my local timezone). I need it to output the time in UTC so I can store it inside of my databases.
System.out.println("DATETIME = " + utc.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
You do too much when trying to convert to old java.util.Date. And then you implicitly use its method toString() which should be well known for the observed behaviour to print the instant always in your system timezone.
But printing in UTC timezone is extremely simple, not even a formatter is needed if you can cope with ISO-8601-notation:
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println("DATETIME = " + utc.toInstant());
// output: DATETIME = 2015-12-30T15:01:18.483Z (Instant is always printed with UTC offset)
System.out.println("DATETIME = " + utc);
// output: DATETIME = 2015-12-30T15:01:57.611Z (the same because you
// have explicitly set the UTC Offset when constructing the ZonedDateTime)
You see, the behaviour of toString() of the new Java-8 classes Instant and ZonedDateTime is much clearer and is always in ISO-format. No need for a confusing conversion to Date.
About specialized formatters, you will only need one if you intend to deviate from ISO-8601-format - maybe using localized month names or extra printing of weekdays etc. Example in US-style:
System.out.println(
"DATETIME = "
+ utc.format(DateTimeFormatter.ofPattern("MM/dd/uuuu h:mm:ss a xxx")));
// output: DATETIME = 12/30/2015 3:14:50 PM +00:00
Note that the answer of #LowLevel uses a wrong pattern. If you leave out the symbol a (AM/PM-marker) then you should not choose the half-day-hour-symbol h but H (24-hour-format). And the timezone or offset symbol (here x) is crucial because otherwise the printed datetime will not be automatically recognized as being in UTC timezone.
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
final SimpleDateFormat sdf = new SimpleDateFormat("EEE, MMM d, yyyy hh:mm:ss a z"); // you can specify format that you want to get
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC time: " + sdf.format(utc));
private Calendar getUTCTime(){
Calendar calendar = Calendar.getInstance();
// Assuming your time is in utc + 8
calendar.add(Calendar.HOUR, -8);
return calendar;
}
I suggest you to use Joda-Time.
DateTime dt = new DateTime(DateTimeZone.UTC);

Categories

Resources