- Convert Java long type value of specific format to seconds/milliseconds
- 3 Answers 3
- Using a date/time parser
- Using arithmetic
- Using LocalDateTime to do the arithmetic
- tl;dr
- Details
- About java.time
- Joda-Time
- ISO 8601
- Period Class
- Duration Class
- Example Code
- How to convert yyy/MM/ss hh:mm:ss into seconds?
- How to convert getTime to seconds?
Convert Java long type value of specific format to seconds/milliseconds
How to convert long value of specific format to seconds or milliseconds in an efficient way. Example long value we have in our system is 20210425 which represent the date of format yyyyMMdd.
I need to convert above to seconds or milliseconds, the desired output I’m looking here would be: 1619308800000
«I need to convert above to seconds or milliseconds» but you say the value represents a local date, that is, a 24h (ish) long period in an unspecified time zone. To convert to seconds/millis, you need to specify the zone and the time within that day (e.g. the start of the day).
3 Answers 3
First of all, you shouldn’t be using a long to represent a date like that. A date is not an integer. (Just like phone numbers and credit cards are not integers.)
However, if you already have a dates represented as a long values . like that . then there are a couple of ways to approach this.
Using a date/time parser
First you need to do is to convert the long to a String ; e.g. using Long.toString(long) .
Then you use a date parser to convert the string a date/time object
Finally you get the millisecond time from the date/time object
Using arithmetic
First do some arithmetic to extract the year, month and day numbers from your long .
Next do some more arithmetic to convert the year / month / day to a number of days since Jan 1st 1970. This is non-trivial because you need to account for leap years AND the fact that different months have different numbers of days.
Finally multiply by the number of milliseconds in a day.
Using LocalDateTime to do the arithmetic
There is another way too. Use arithmetic to extract the year, month and day as above.
Then use LocalDateTime.of(year, month, day, 0, 0) to create a LocalDateTime . (Make sure that month and day are based correctly!)
Finally get the millisecond time from the LocalDateTime object
A final note. As Andy Turner points out in a comment, you haven’t specified what timezone the long is based on or the timezone of the millisecond clock that you are targeting. These will need to be taken into account . no matter what method you use to do the conversion.
tl;dr
Do not use math for date-time handling. We have the java.time classes for that.
LocalDate // Represent a date-only value, without a time-of-day and without a time zone or offset-from-UTC. .parse( // Interpret a piece of text as representing a date value. String.valueOf( 20210425L ) , // Becomes a `String` object, "20210425". DateTimeFormatter.BASIC_ISO_DATE // YYYYMMDD format. ) // Returns a `LocalDate` object. .atStartOfDay( ZoneOffset.UTC ) // Determine the first moment of the day in that time zone or offset. .toInstant() // Adjust from some offset to an offset of zero hours-minutes-seconds. .toEpochMilli() // Calculate a count of milliseconds since the epoch reference of first moment of 1970 UTC.
Details
Read all of the valid points in the correct Answer by Stephen C. Then consider this code solution.
Convert your long variable to text, and parse as a date. More preferable would be skipping the long altogether if possible, for reasons discussed in that other Answer.
The textual version of your number 20210425 happens to be representing a date using the “basic” (compact) version of the standard ISO 8601 format for dates. The DateTimeFormatter class has a constant with that format predefined, DateTimeFormatter.BASIC_ISO_DATE .
long val = 20210425; String input = String.valueOf( val ) ; DateTimeFormatter f = DateTimeFormatter.BASIC_ISO_DATE ; LocalDate localDate = LocalDate.parse( input , f ) ;
Apparently you want a count of milliseconds since the first moment of 1970 in UTC. And apparently you want to interpret that input as being seen in UTC (an offset of zero hours-minutes-seconds).
So apply an offset of zero to the date while getting the first moment of the day, to produce a ZonedDateTime . From that extract a Instant , the basic building block of java.time, always in UTC by definition.
Instant instant = localDate.atStartOfDay( ZoneOffset.UTC ).toInstant() ;
Get a count of milliseconds since the epoch reference of 1970-01-01T00:00Z.
long millisecondsSinceEpoch = instant.toEpochMilli() ;
localDate.toString(): 2021-04-25
instant.toString(): 2021-04-25T00:00:00Z
millisecondsSinceEpoch: 1619308800000
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat .
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later — Part of the standard Java API with a bundled implementation.
- Java 9 brought some minor features and fixes.
- Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Later versions of Android (26+) bundle implementations of the java.time classes.
- For earlier Android (<26), the process of API desugaring brings a subset of the java.time functionality not originally built into Android.
- If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
Joda-Time
Don’t reinvent the wheel. The Joda-Time library can parse those values for you. No need for regex.
ISO 8601
Those values are close to being in standard ISO 8601 format. Specifically the Durations format, PnYnMnDTnHnMnS . The P marks the beginning, the T separates the date portion from the time position. If you have time-only values, then simply prepend the PT to get PT33m03s . Lastly convert to uppercase to get PT33M03S .
Joda-Time both parses and generates such strings by default. Once your input is in standard format, you can pass it directly to Joda-Time. Skip the regex.
Alternatively, you can specify a PeriodFormatter to fit your exact input strings. Then you can parse the original input strings without converting to standard format.
If you have any control or influence over the source of your input strings, I strongly suggest altering that source to utilize the ISO 8601 format.
Period Class
Next, use the Period class to automatically parse that value into a Period object. A Period represents a span of time as a number of months, days, hours, and such. Not tied to points on the timeline of the history of the Universe. (If you have specific points on a timeline, use the Interval class.)
Duration Class
Next, call toStandardDuration to get a Duration object. A Duration in Joda-Time represents a span of time as just the passage of time. Merely a number of milliseconds, not a specific number of months or hours or such chunks.
Lastly, on that Duration object call getStandardSeconds to get your answer.
Much easier than dealing with regex. And more reliable as Joda-Time is already built, debugged, well-worn, and able to handle the various permutations of possible input strings.
Example Code
Succinct version (not recommended).
String input = ( "PT" + "33m03s" ).toUpperCase(); long durationInSeconds = Period.parse( input ).toStandardDuration().getStandardSeconds();
// Convert input string to standard ISO 8601 format. // Alternatively, you could use a formatter to parse your original string rather than convert. String inputRaw = "33m03s"; String inputStandard = "PT" + inputRaw; // Assuming this is a time-only without date portion, prepend 'PT' to make standard ISO 8601 format. inputStandard = inputStandard.toUpperCase(); // Parse string as Period object. Period period = Period.parse( inputStandard ); // Convert from Period to Duration to extract total seconds. Duration duration = period.toStandardDuration(); long durationInSeconds = duration.getStandardSeconds(); // Returns getMillis() / 1000. The result is an integer division, so 2999 millis returns 2 seconds.
System.out.println( "inputRaw : " + inputRaw ); System.out.println( "inputStandard : " + inputStandard ); System.out.println( "period : " + period ); // Notice how the leading zero on the 'seconds' number is gone. We have a Period *object*, not messing with strings. System.out.println( "duration : " + duration ); System.out.println( "durationInSeconds : " + durationInSeconds );
inputRaw : 33m03s inputStandard : PT33M03S period : PT33M3S duration : PT1983S durationInSeconds : 1983
How to convert yyy/MM/ss hh:mm:ss into seconds?
Introduction I’m trying to get the difference in seconds from two Epochs i.e 2019-05-22 18:28:56 -> 1558542536 seconds 2019-07-22 19:00:00 -> 1563814800 seconds The diff will be: 5,272,264 seconds This date format comes from a binary file as a String My code
public static void main(String[] args) throws ParseException < String regEpoch = ""; long result = 0; //System.out.println((fecha = dateFormat.format(date))); try(RandomAccessFile raf = new RandomAccessFile("binario2.txt", "rw"))< //user inputs a code (for now, doesn't matter if exists or not) System.out.print("Input a code to look for: "); String code = scan.next(); while(!code.matches("\\d+")) < System.out.println("[ERROR] Only digits accepted"); System.out.print("Input a code to look for: "); code = scan.next(); >//Gets the current date in seconds long getSecs = (new Date().getTime())/1000; System.out.println("Current tiem in secs: " + getSecs); //We are "randomly accessing" a binary file. The is no problem here at all. It just works. //Sets the pointer where I want it, again. this works fine. raf.seek(27+(80*Integer.parseInt(code))); //Read the String date correctly, which is 2019-05-22 18:28:56 System.out.println(raf.readUTF()); /* //Attempt 2 System.out.println(java.time.Instant.ofEpochSecond(Long.parseLong(raf.readUTF()))); Long millis = new SimpleDateFormat("yyyy/MM/ss hh:mm:ss").parse(raf.readUTF()).getTime(); System.out.println(millis); */ //Let's try to convert it into seconds. No we can't due to -> Unparseable date: "2019-05-22 18:28:56" Date dt = dateFormat.parse(raf.readUTF()); long epoch = dt.getTime(); System.out.println("Result is: " + (int)(epoch*1000)); >catch(IOException e)
> So far what I tried only gets the seconds from the Date with SimpleDateFormat but those are not what I expected.
What do I expect from this
I am currently doing homework and I have been task with calculating the price for a parking ticket and I thought, what if the car doesn’t leave, let’s say. in a week?
If I work only in the format of hh:mm:ss those cars who stay there a whole week will only pay for one day.
How to convert getTime to seconds?
Call getTime to get the number of milliseconds since January 1, 1970. Divide by 1000 to get it in seconds:
long unixTime = from_time.getTime() / 1000;
To get the number of seconds since 00:00 of the current day, use the
Calendar c = Calendar(); c.setTime(from_time); long daySeconds = (c.get(Calendar.SECONDS) + c.get(Calendar.MINUTES) * 60 + c.get(Calendar.HOURS) * 3600);
@maas Fortunately, converting milliseconds to seconds is really easy: Just divide by 1000. Added text to the code that already did this.
It converted the time to an incorrect value. The time is 00:04:00 which is 4 minutes and in the conversion it showed -10560000
@maas That’s because UNIX time calculates the number of seconds from 1970 till now, instead of the start of the current day till now. Updated with a solution that calculates the number of seconds in a day.
long seconds = rs.getTime(«nfrm_time»).getTime() / 1000
rs.getTime(«nfrm_time») returns java.sql.Time which is actually a sub class of java.util.Date .
java.util.Date.getTime() returns time in milli seconds which we divide by 1000 to get seconds.
If you’re looking for duration instead,
Calendar cal = Calendar.getInstance(); cal.setTime(rs.getTime("nfrm_time")); // set to the time returned by resultset cal.set(0, 0, 0); // reset the year, month and date fields Calendar cal2 = Calendar.getInstance(); cal2.set(0, 0, 0, 0, 0, 0); // reset all the fields, including time long duration = ((cal.getTimeInMillis() - cal2.getTimeInMillis()) / 1000) + 1;