Getting Unix timestamp from the past with java 8 - java

since Java 8 I can use instant and LocalDateTime
To get the Unix timestamp:
long unixTimestamp = Instant.now().getEpochSecond();
But if I want to get a time from the past, lets say 2 weeks I use this:
int unixtime2weeksAgo = (int) ((System.currentTimeMillis() - 24 * 60 * 60 * 1000 * 14) / 1000L)
With the docu I couldn't build a solution based on the new java 8 features is here someone who could provide a good solution by using instant or LocalDateTime?

"Two weeks ago" is dependent on your time zone (there may have been some DST changes etc.). So using Instant or LocalDateTime may create issues because they don't include any time zone information.
Assuming you want to do it in UTC, you can use:
ZonedDateTime twoWeeksAgo = ZonedDateTime.now(ZoneOffset.UTC).minusWeeks(2);
long unixTs = twoWeeksAgo.toEpochSecond();
You can specify a different time zone in place of ZoneOffset.UTC seen above. For example, ZoneId.of( "Asia/Kolkata" ).

see below:
import java.time.Instant;
import java.time.temporal.ChronoUnit;
public class TimestampExample {
public static void main(String[] args) {
long currentUnixTimestamp = Instant.now().getEpochSecond();
System.out.println(currentUnixTimestamp);
// two weeks ago
long pastTimestamp = Instant.now().minus(14, ChronoUnit.DAYS).getEpochSecond();
System.out.println(pastTimestamp);
}
}

Related

How to generate a random time between two times say 4PM and 2AM?

I have tried using -
int startSeconds = restaurant.openingTime.toSecondOfDay();
int endSeconds = restaurant.closingTime.toSecondOfDay();
LocalTime timeBetweenOpenClose = LocalTime.ofSecondOfDay(ThreadLocalRandom.current().nextInt(startSeconds, endSeconds));
But this usually runs into an error as in nextInt(origin, bounds), origin can't be less than bounds which will happen if my openingTime is 16:00:00 and closingTime is 02:00:00.
You can add the seconds of one day(24*60*60) when startSeconds is greater than endSeconds to represent the next day's second and after getting a random number modulo it by the seconds of one day to convert it into LocalTime by a valid second value.
int secondsInDay = (int)Duration.ofDays(1).getSeconds();
if(startSeconds > endSeconds){
endSeconds += secondsInDay;
}
LocalTime timeBetweenOpenClose = LocalTime.ofSecondOfDay(
ThreadLocalRandom.current().nextInt(startSeconds, endSeconds) % secondsInDay);
We cannot know how much time will elapse between 4 PM and 2 AM without applying a date and time zone. Therefore, we will solve it using ZonedDateTime.
The first step will be: obtain a ZonedDateTime by calling LocalDate#atStartOfDay
ZoneId zoneId = ZoneId.systemDefault();
LocalDate.now().atStartOfDay(zoneId);
Next, use ZonedDateTime#with to get a ZonedDateTime with the specified time.
Now, you can derive an Instant from a ZonedDateTime using ZonedDateTime#toInstant.
Once you have the start and end Instants derived this way, you can use ThreadLocalRandom.current().nextLong to generate a long value in the range of the start and the end Instants and use the obtained value to get the required Instant.
Finally, you can derive a ZonedDateTime from this Instant using Instant#atZone and then get the required time using ZonedDateTime#toLocalTime.
Demo:
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.concurrent.ThreadLocalRandom;
public class Main {
public static void main(String[] args) {
// Change it as per the applicable timezone e.g. ZoneId.of("Europe/London")
ZoneId zoneId = ZoneId.systemDefault();
LocalDate today = LocalDate.now();
ZonedDateTime zdtStart = today.atStartOfDay(zoneId)
.with(LocalTime.of(16, 0));
ZonedDateTime zdtEnd = today.plusDays(1)
.atStartOfDay(zoneId)
.with(LocalTime.of(2, 0));
ZonedDateTime zdtResult =
Instant.ofEpochMilli(
ThreadLocalRandom
.current()
.nextLong(
zdtStart.toInstant().toEpochMilli(),
zdtEnd.toInstant().toEpochMilli()
)
).atZone(zoneId);
LocalTime time = zdtResult.toLocalTime();
System.out.println(time);
}
}
Learn more about the modern date-time API from Trail: Date Time.
ONLINE DEMO printing 100 random times.

Pulling time from api/json and comparing it to a set date

System.out.println(json.toString());
System.out.println(json.get("date"));
returns time in epoch time such as: 1609642292
> Task :Program:DateUtils.main()
{"date":1609642292}
1609642292
This is what I'm using to pull the date from the API
import java.io.InputStreamReader;
import java.net.URL;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.Date;
import org.json.JSONException;
import org.json.JSONObject;
public class DateUtils
{
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
// InputStream is = new URL(url).openStream();
try (var is = new URL(url).openStream()) {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
}
}
public static void main(String[] args) throws IOException, JSONException {
JSONObject json = readJsonFromUrl("https://Time.xyz/api/date"); //Don't want to post real API
System.out.println(json.toString());
System.out.println(json.get("date"));
}
}
In my other java file I'm trying to do something like
Calendar expiry = Calendar.getInstance();
expiry.set(2021,1,31,0,0) //When my program expires:year, month, date, hour, min
Calendar now = DateUtils.getAtomicTime();
//where DateUtils.getAtomicTime comes from this class that pulls current time from the National Institute of Standards and Technology
//https://www.rgagnon.com/javadetails/java-0589.html
if (now.after(expiry)) {
shutdown()
}else{
startProgram()
}
}
How can I change
Calendar now - DateUtils.getatomicTime() to this new API
My problems:
I don't know how to use what I have to check for the time and refer to it.
Like it prints the time properly, but now how do I use that println jsontostring and then use that to add it to that code slightly above to compare my Set Expiration Date with API date.
Please give me some advice. Thank you.
It appears that the goal is to use the epoch time in the date element of the server response and call shutdown if that is earlier than the current time.
Instead of creating Calendar instances, I would compare the current epoch time to the value in the HTTP response.
if (DateUtils.readJsonFromUrl("https://Time.xyz/api/date").get("date") * 1000 < System.currentTimeMillis()) {
shutdown();
} else {
startProgram();
}
tl;dr
Your Question is not clear. But it seems you want to compare some moment represented as a textual number of whole seconds since 1970-01-01T00:00Z to some number of calendar days past the current moment as captured from a remote time server using some library you’ve not explained.
boolean isFurtherOutIntoTheFuture =
Instant // Represent a moment, a point on the timeline, resolving to nanoseconds, as seen in UTC.
.ofEpochSecond( // Interpret a number as a count of whole seconds since the epoch reference point of 1970-01-01T00:00Z.
Long.parseLong( "1609642292" ) // Parse text as a number, a 64-bit `long`.
) // Returns a `Instant`.
.isAfter( // Compare one `Instant` object to another.
DateUtils // Some mysterious library that fetches current moment from a remote time server.
.getAtomicTime() // Returns a `java.until.Date` object (apparently – not explained in Question).
.toInstant() // Convert from legacy class to its modern replacement.
.atZone( // Adjust from UTC to some time zone. Same moment, different wall-clock time.
ZoneId.of( "Africa/Tunis" ) // Whatever time zone by which you want to add some number of calendar days.
) // Returns a `ZonedDateTime` object.
.plusDays( x ) // Add some number of calendar days (*not* necessarily 24-hours long). Returns a new `ZonedDateTime` object with values based on the original.
.toInstant() // Adjust from some time zone to UTC (an offset-from-UTC of zero hours, minutes, and seconds).
) // Returns a `boolean`.
;
Details
Never use Calendar. That terrible class was supplanted years ago by the modern java.time classes.
Convert your epoch seconds to Instant by calling Instant.ofEpochSecond. Pass a long parsed from your textual input.
Apparently a call to the DateUtils.getAtomicTime, of some library you neglected to mention, results in Java.until.Date. Convert that terrible legacy class to its modern replacement, java.time.Instant. Notice the new to… and from… conversion methods added to the old legacy classes.
Instant now = DateUtils.getAtomicTime().toInstant() ;
Compare to current moment.
boolean isInTheFuture = someInstant.isAfter( now ) ;
You commented about “x amount of days”. Did you mean calendars days or generic chunks of 24-hours? If the latter:
Instant later = myInstant.plus( Duration.ofDays( x ) ) ;
If you meant calendar days, apply a time zone.
ZoneId z = ZoneId.of( "America/Edmonton" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
ZonedDateTime later = zdt.plusDays( x ) ;
Instant laterInUtc = later.toInstant() ;
All of this has been covered many many many times already on Stack Overflow. Search to learn more.
The answer by Basil Bourque guides you in the right direction. This answer is focused on what code you should write.
The class, Instant serves as the bridge between the legacy date-time API and the modern date-time API. Convert the java.util.Calendar object (which you are getting from json.get("date")) to Instant using Calendar#toInstant.
For expiry date, you can create an Instant object using the OffsetDateTime object set with ZoneOffset.UTC.
Finally, you can compare these two objects of Instant using Instant#isAfter.
Based on the explanation given above, you need to write the following code:
JSONObject json = readJsonFromUrl("https://Time.xyz/api/date");
Calendar now = json.get("date");
Instant instantNow = now.toInstant();
Instant expiry = OffsetDateTime.of(LocalDateTime.of(2021, 1, 31, 0, 0), ZoneOffset.UTC).toInstant();
if (instantNow.isAfter(expiry)) {
shutdown();
} else {
startProgram();
}
Learn about the modern date-time API from Trail: Date Time.
Note that the date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.
For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

What is the jconsole time format?

I have monitored my java program using jconsole recently. I saved CPU usage data as a csv file. This is what I've got:
Time,CPU Usage
43690.008014,1,8
43690.008060,0,1
43690.008106,0,1
43690.008153,0,1
43690.008199,0,1
43690.008245,0,1
The CPU Usage column is clear, but I cannot say the same thing about the Time column. What is 43690.008014? How can I parse it into Date? I haven't seen anything like this in my life.
The duration recorded in the CSV file is the number of days since 1899-12-311. In order to get the current date, you can add this duration to LocalDate.of(1899, 12, 30).atStartOfDay().atOffset(ZoneOffset.UTC). I recommend you use java.time.Duration which is modelled on ISO-8601 standards and was introduced with Java-8 as part of JSR-310 implementation. The function, Duration#ofNanos gives you a Duration representing the specified number of nanoseconds. The reason why I am recommending you to use this function despite the fact that there is already a function, Duration#ofDays is that these functions take a long value as the argument and if you cast the duration in your log file (e.g. 43690.008014) to long, its fractional part will be lost giving you an incorrect result.
Therefore, convert these days to nanoseconds, get Duration from the resulting nanoseconds and add the same to LocalDate.of(1899, 12, 30).atStartOfDay().atOffset(ZoneOffset.UTC) to get the current date and time in UTC.
Demo:
import java.time.Duration;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class Main {
public static void main(String[] args) {
OffsetDateTime startDateTime = LocalDate.of(1899, 12, 30).atStartOfDay().atOffset(ZoneOffset.UTC);
OffsetDateTime current = startDateTime
.plus(Duration.ofNanos((long) (43690.008014 * 24 * 60 * 60 * 1000_000_000)));
System.out.println(current);
}
}
Output:
2019-08-13T00:11:32.409600512Z
Learn about the modern date-time API from Trail: Date Time.
For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
1 Why is 1899-12-30 the zero date in Access / SQL Server instead of 12/31?
The time format is daysSinceEpoch.fractionOfCurrentDay
The daysSinceEpoch starting at 1899-12-30 instead of 1900-01-01
The fractionOfCurrentDay is a millionth of the current day, ranging from zero to 999999 (23:59:59)
You can use the following function to convert to LocalDateTime:
public static LocalDateTime convert( final String jconsoleDateFormat )
{
String[] split = jconsoleDateFormat.split( "\\." );
long daysSinceEpoch = Long.parseLong( split[0] );
long dayFraction = Long.parseLong( split[1] );
LocalDateTime epochDate = LocalDateTime.of( 1899,12,30, 0,0 );
LocalDateTime currentDate = epochDate.plusDays( daysSinceEpoch );
long secondsADay = 24 * 60 * 60L; // 86_400
long secondsSinceDayStarted = secondsADay * dayFraction / 1_000_000;
return currentDate.plusSeconds( secondsSinceDayStarted );
}
public static void main( String[] args )
{
System.out.println( convert( "43690.008014" ) ); // 2019-08-13T00:11:32
}

How to measure time elapsed, immune to system time server automatic updates [duplicate]

This question already has answers here:
How do I time a method's execution in Java?
(42 answers)
How do I calculate the elapsed time of an event in Java? [duplicate]
(6 answers)
Closed 4 years ago.
I want to have something like this:
public class Stream
{
public startTime;
public endTime;
public getDuration()
{
return startTime - endTime;
}
}
Also it is important that for example if the startTime it's 23:00 and endTime 1:00 to get a duration of 2:00.
Which types to use in order to accomplish this in Java?
Unfortunately, none of the ten answers posted so far are quite right.
If you are measuring elapsed time, and you want it to be correct, you must use System.nanoTime(). You cannot use System.currentTimeMillis(), unless you don't mind your result being wrong.
The purpose of nanoTime is to measure elapsed time, and the purpose of currentTimeMillis is to measure wall-clock time. You can't use the one for the other purpose. The reason is that no computer's clock is perfect; it always drifts and occasionally needs to be corrected. This correction might either happen manually, or in the case of most machines, there's a process that runs and continually issues small corrections to the system clock ("wall clock"). These tend to happen often. Another such correction happens whenever there is a leap second.
Since nanoTime's purpose is to measure elapsed time, it is unaffected by any of these small corrections. It is what you want to use. Any timings currently underway with currentTimeMillis will be off -- possibly even negative.
You may say, "this doesn't sound like it would ever really matter that much," to which I say, maybe not, but overall, isn't correct code just better than incorrect code? Besides, nanoTime is shorter to type anyway.
Previously posted disclaimers about nanoTime usually having only microsecond precision are valid. Also it can take more than a whole microsecond to invoke, depending on circumstances (as can the other one), so don't expect to time very very small intervals correctly.
Which types to use in order to accomplish this in Java?
The short answer is a long. Now, more on how to measure...
System.currentTimeMillis()
The "traditional" way to do this is indeed to use System.currentTimeMillis():
long startTime = System.currentTimeMillis();
// ... do something ...
long estimatedTime = System.currentTimeMillis() - startTime;
o.a.c.l.t.StopWatch
Note that Commons Lang has a StopWatch class that can be used to measure execution time in milliseconds. It has methods methods like split(), suspend(), resume(), etc that allow to take measure at different points of the execution and that you may find convenient. Have a look at it.
System.nanoTime()
You may prefer to use System.nanoTime() if you are looking for extremely precise measurements of elapsed time. From its javadoc:
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
Jamon
Another option would be to use JAMon, a tool that gathers statistics (execution time, number of hit, average execution time, min, max, etc) for any code that comes between start() and stop() methods. Below, a very simple example:
import com.jamonapi.*;
...
Monitor mon=MonitorFactory.start("myFirstMonitor");
...Code Being Timed...
mon.stop();
Check out this article on www.javaperformancetunning.com for a nice introduction.
Using AOP
Finally, if you don't want to clutter your code with these measurement (or if you can't change existing code), then AOP would be a perfect weapon. I'm not going to discuss this very deeply but I wanted at least to mention it.
Below, a very simple aspect using AspectJ and JAMon (here, the short name of the pointcut will be used for the JAMon monitor, hence the call to thisJoinPoint.toShortString()):
public aspect MonitorAspect {
pointcut monitor() : execution(* *.ClassToMonitor.methodToMonitor(..));
Object arround() : monitor() {
Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString());
Object returnedObject = proceed();
monitor.stop();
return returnedObject;
}
}
The pointcut definition could be easily adapted to monitor any method based on the class name, the package name, the method name, or any combination of these. Measurement is really a perfect use case for AOP.
Your new class:
public class TimeWatch {
long starts;
public static TimeWatch start() {
return new TimeWatch();
}
private TimeWatch() {
reset();
}
public TimeWatch reset() {
starts = System.currentTimeMillis();
return this;
}
public long time() {
long ends = System.currentTimeMillis();
return ends - starts;
}
public long time(TimeUnit unit) {
return unit.convert(time(), TimeUnit.MILLISECONDS);
}
}
Usage:
TimeWatch watch = TimeWatch.start();
// do something
long passedTimeInMs = watch.time();
long passedTimeInSeconds = watch.time(TimeUnit.SECONDS);
Afterwards, the time passed can be converted to whatever format you like, with a calender for example
Greetz,
GHad
If the purpose is to simply print coarse timing information to your program logs, then the easy solution for Java projects is not to write your own stopwatch or timer classes, but just use the org.apache.commons.lang.time.StopWatch class that is part of Apache Commons Lang.
final StopWatch stopwatch = new StopWatch();
stopwatch.start();
LOGGER.debug("Starting long calculations: {}", stopwatch);
...
LOGGER.debug("Time after key part of calcuation: {}", stopwatch);
...
LOGGER.debug("Finished calculating {}", stopwatch);
tl;dr
for example if the startTime it's 23:00 and endTime 1:00 to get a duration of 2:00.
Not possible. If you have only time-of-day, the clock stops at midnight. Without the context of dates, how do we know if you mean 1 AM on the next day, next week, or next decade?
So going from 11 PM to 1 AM means moving backwards in time 22 hours, running the hands of the clock counterclockwise. See the result below, a negative twenty-two hours.
Duration.between( // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
LocalTime.of( 23 , 0 ) , // A time-of-day without a date and without a time zone.
LocalTime.of( 1 , 0 ) // A time-of-day clock stops at midnight. So getting to 1 AM from 11 PM means going backwards 22 hours.
) // Return a `Duration` object.
.toString() // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS
PT-22H
Crossing midnight requires the larger context of date in addition to time-of-day (see below).
How do I measure time elapsed in Java?
Capture the current moment in UTC, with Instant.now().
Capture another such moment later.
Pass both to Duration.between.
(a) From the resulting Duration object, extract a number of 24-hour days, hours, minutes, seconds, and fractional second in nanoseconds by calling the various to…Part methods.(b) Or, call toString to generate a String in standard ISO 8601 format of PnYnMnDTnHnMnS.
Example code, using pair of Instant objects.
Duration.between( // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
then , // Some other `Instant` object, captured earlier with `Instant.now()`.
Instant.now() // Capture the current moment in UTC with a resolution as fine as nanoseconds, depending on the limits of your host computer hardware clock and operating system. Generally you will get current moment in microseconds (six decimal digits of fractional second) in Java 9, 10, and 11, but only milliseconds in Java 8.
) // Return a `Duration` object.
.toString() // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS
PT3M27.602197S
New Technology In Java 8+
We have new technology for this now built into Java 8 and later, the java.time framework.
java.time
The java.time framework is defined by JSR 310, inspired by the highly successful Joda-Time project, extended by the ThreeTen-Extra project, and described in the Oracle Tutorial.
The old date-time classes such as java.util.Date/.Calendar bundled with the earliest versions of Java have proven to be poorly designed, confusing, and troublesome. They are supplanted by the java.time classes.
Resolution
Other answers discuss resolution.
The java.time classes have nanosecond resolution, up to nine digits of a decimal fraction of a second. For example, 2016-03-12T04:29:39.123456789Z.
Both the old java.util.Date/.Calendar classes and the Joda-Time classes have millisecond resolution (3 digits of fraction). For example, 2016-03-12T04:29:39.123Z.
In Java 8, the current moment is fetched with up to only millisecond resolution because of a legacy issue. In Java 9 and later, the current time can be determined up to nanosecond resolution provided your computer’s hardware clock runs so finely.
Time-Of-Day
If you truly want to work with only the time-of-day lacking any date or time zone, use the LocalTime class.
LocalTime sooner = LocalTime.of ( 17, 00 );
LocalTime later = LocalTime.of ( 19, 00 );
A Duration represents a span of time it terms of a count of seconds plus nanoseconds.
Duration duration = Duration.between ( sooner, later );
Dump to console.
System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );
sooner: 17:00 | later: 19:00 | duration: PT2H
ISO 8601
Notice the default output of Duration::toString is in standard ISO 8601 format. In this format, the P marks the beginning (as in 'Period'), and the T separates any years-months-days portion from the hours-minutes-seconds portion.
Crossing Midnight
Unfortunately, working with time-of-day only gets tricky when you wrap around the clock crossing midnight. The LocalTime class handles this by assuming you want to go backwards to an earlier point in the day.
Using the same code as above but going from 23:00 to 01:00 results in a negative twenty-two hours (PT-22H).
LocalTime sooner = LocalTime.of ( 23, 0 );
LocalTime later = LocalTime.of ( 1, 0 );
sooner: 23:00 | later: 01:00 | duration: PT-22H
Date-Time
If you intend to cross midnight, it probably makes sense for you to be working with date-time values rather than time-of-day-only values.
Time Zone
Time zone is crucial to dates. So we specify three items: (1) the desired date, (2) desired time-of-day, and (3) the time zone as a context by which to interpret that date and time. Here we arbitrarily choose the time zone of the Montréal area.
If you define the date by only an offset-from-UTC, use a ZoneOffset with a OffsetDateTime. If you have a full time zone (offset plus rules for handling anomalies such as Daylight Saving Time), use a ZoneId with a ZonedDateTime.
LocalDate localDate = LocalDate.of ( 2016, 1, 23 );
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime sooner = ZonedDateTime.of ( localDate, LocalTime.of ( 23, 0 ), zoneId );
We specify the later time as next day at 1:00 AM.
ZonedDateTime later = ZonedDateTime.of ( localDate.plusDays ( 1 ), LocalTime.of ( 1, 0 ), zoneId );
We calculate the Duration in the same manner as seen above. Now we get the two hours expected by this Question.
Duration duration = Duration.between ( sooner, later );
Dump to console.
System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );
sooner: 2016-01-23T23:00-05:00[America/Montreal] | later: 2016-01-24T01:00-05:00[America/Montreal] | duration: PT2H
Daylight Saving Time
If the date-times at hand had involved Daylight Saving Time (DST) or other such anomaly, the java.time classes would adjust as needed. Read class doc for details.
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.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
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.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
It is worth noting that
System.currentTimeMillis() has only millisecond accuracy at best. At worth its can be 16 ms on some windows systems. It has a lower cost that alternatives < 200 ns.
System.nanoTime() is only micro-second accurate on most systems and can jump on windows systems by 100 microseconds (i.e sometimes it not as accurate as it appears)
Calendar is a very expensive way to calculate time. (i can think of apart from XMLGregorianCalendar) Sometimes its the most appropriate solution but be aware you should only time long intervals.
Which types to use in order to accomplish this in Java?
Answer: long
public class Stream {
public long startTime;
public long endTime;
public long getDuration() {
return endTime - startTime;
}
// I would add
public void start() {
startTime = System.currentTimeMillis();
}
public void stop() {
endTime = System.currentTimeMillis();
}
}
Usage:
Stream s = ....
s.start();
// do something for a while
s.stop();
s.getDuration(); // gives the elapsed time in milliseconds.
That's my direct answer for your first question.
For the last "note" I would suggest you to use Joda Time. It contains an interval class suitable for what you need.
Java provides the static method System.currentTimeMillis(). And that's returning a long value, so it's a good reference. A lot of other classes accept a 'timeInMillis' parameter which is long as well.
And a lot of people find it easier to use the Joda Time library to do calculations on dates and times.
If you prefer using Java's Calendar API you can try this,
Date startingTime = Calendar.getInstance().getTime();
//later on
Date now = Calendar.getInstance().getTime();
long timeElapsed = now.getTime() - startingTime.getTime();
If you are writing an application that must deal with durations of time, then please take a look at Joda-Time which has class specifically for handling Durations, Intervals, and Periods. Your getDuration() method looks like it could return a Joda-Time Interval:
DateTime start = new DateTime(2004, 12, 25, 0, 0, 0, 0);
DateTime end = new DateTime(2005, 1, 1, 0, 0, 0, 0);
public Interval getInterval() {
Interval interval = new Interval(start, end);
}
Byte Stream Reader Elapsed Time for 23.7 MB is 96 secs
import java.io.*;
import java.io.IOException;
import java.util.Scanner;
class ElaspedTimetoCopyAFileUsingByteStream
{
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start()
{
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop()
{
this.stopTime = System.currentTimeMillis();
this.running = false;
}
public long getElapsedTime()
{
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
public long getElapsedTimeSecs()
{
long elapsed;
if (running)
{
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else
{
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
public static void main(String[] args) throws IOException
{
ElaspedTimetoCopyAFileUsingByteStream s = new ElaspedTimetoCopyAFileUsingByteStream();
s.start();
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("vowels.txt"); // 23.7 MB File
out = new FileOutputStream("output.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
s.stop();
System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
}
}
[Elapsed Time for Byte Stream Reader][1]
**Character Stream Reader Elapsed Time for 23.7 MB is 3 secs**
import java.io.*;
import java.io.IOException;
import java.util.Scanner;
class ElaspedTimetoCopyAFileUsingCharacterStream
{
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start()
{
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop()
{
this.stopTime = System.currentTimeMillis();
this.running = false;
}
public long getElapsedTime()
{
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
public long getElapsedTimeSecs()
{
long elapsed;
if (running)
{
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else
{
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
public static void main(String[] args) throws IOException
{
ElaspedTimetoCopyAFileUsingCharacterStream s = new ElaspedTimetoCopyAFileUsingCharacterStream();
s.start();
FileReader in = null; // CharacterStream Reader
FileWriter out = null;
try {
in = new FileReader("vowels.txt"); // 23.7 MB
out = new FileWriter("output.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
s.stop();
System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
}
}
[Elapsed Time for Character Stream Reader][2]
[1]: https://i.stack.imgur.com/hYo8y.png
[2]: https://i.stack.imgur.com/xPjCK.png
If you're getting your timestamps from System.currentTimeMillis(), then your time variables should be longs.
i found this code to be useful when timing things:
public class Et {
public Et() {
reset();
}
public void reset() {
t0=System.nanoTime();
}
public long t0() {
return t0;
}
public long dt() {
return System.nanoTime()-t0();
}
public double etms() {
return etms(dt());
}
#Override public String toString() {
return etms()+" ms.";
}
public static double etms(long dt) {
return dt/1000000.; // 1_000_000. breaks cobertura
}
private Long t0;
}
Use this:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date d1 = format.parse(strStartTime);
Date d2 = format.parse(strEndTime);
long diff = d2.getTime() - d1.getTime();
long diffSeconds,diffMinutes,diffHours;
if (diff > 0) {
diffSeconds = diff / 1000 % 60;
diffMinutes = diff / (60 * 1000) % 60;
diffHours = diff / (60 * 60 * 1000);
}
else{
long diffpos = (24*((60 * 60 * 1000))) + diff;
diffSeconds = diffpos / 1000 % 60;
diffMinutes = diffpos / (60 * 1000) % 60;
diffHours = (diffpos / (60 * 60 * 1000));
}
(Also it is important that for example if the startTime it's 23:00 and endTime 1:00 to get a duration of 2:00.)
the "else" part can get it correct
I built a formatting function based on stuff I stole off SO. I needed a way of "profiling" stuff in log messages, so I needed a fixed length duration message.
public static String GetElapsed(long aInitialTime, long aEndTime, boolean aIncludeMillis)
{
StringBuffer elapsed = new StringBuffer();
Map<String, Long> units = new HashMap<String, Long>();
long milliseconds = aEndTime - aInitialTime;
long seconds = milliseconds / 1000;
long minutes = milliseconds / (60 * 1000);
long hours = milliseconds / (60 * 60 * 1000);
long days = milliseconds / (24 * 60 * 60 * 1000);
units.put("milliseconds", milliseconds);
units.put("seconds", seconds);
units.put("minutes", minutes);
units.put("hours", hours);
units.put("days", days);
if (days > 0)
{
long leftoverHours = hours % 24;
units.put("hours", leftoverHours);
}
if (hours > 0)
{
long leftoeverMinutes = minutes % 60;
units.put("minutes", leftoeverMinutes);
}
if (minutes > 0)
{
long leftoverSeconds = seconds % 60;
units.put("seconds", leftoverSeconds);
}
if (seconds > 0)
{
long leftoverMilliseconds = milliseconds % 1000;
units.put("milliseconds", leftoverMilliseconds);
}
elapsed.append(PrependZeroIfNeeded(units.get("days")) + " days ")
.append(PrependZeroIfNeeded(units.get("hours")) + " hours ")
.append(PrependZeroIfNeeded(units.get("minutes")) + " minutes ")
.append(PrependZeroIfNeeded(units.get("seconds")) + " seconds ")
.append(PrependZeroIfNeeded(units.get("milliseconds")) + " ms");
return elapsed.toString();
}
private static String PrependZeroIfNeeded(long aValue)
{
return aValue < 10 ? "0" + aValue : Long.toString(aValue);
}
And a test class:
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import junit.framework.TestCase;
public class TimeUtilsTest extends TestCase
{
public void testGetElapsed()
{
long start = System.currentTimeMillis();
GregorianCalendar calendar = (GregorianCalendar) Calendar.getInstance();
calendar.setTime(new Date(start));
calendar.add(Calendar.MILLISECOND, 610);
calendar.add(Calendar.SECOND, 35);
calendar.add(Calendar.MINUTE, 5);
calendar.add(Calendar.DAY_OF_YEAR, 5);
long end = calendar.getTimeInMillis();
assertEquals("05 days 00 hours 05 minutes 35 seconds 610 ms", TimeUtils.GetElapsed(start, end, true));
}
}

Java TimeZone head scratching

I would like to save some user timezone in a Daylight saving proof format.
My goal is to get the correct GMT offset whenever the code gets executed.
In order to figure out my best option, I wrote the following:
ArrayList<String> list = new ArrayList<String>();
list.add( "EST");
list.add( "EDT");
list.add( "America/New_York");
long now = System.currentTimeMillis();
for( String tzID: list) {
TimeZone tz = TimeZone.getTimeZone( tzID);
System.out.println( tzID + " now=" + tz.getOffset( now) / 3600000 + " / +182=" + tz.getOffset( now + ( 182 * 86400000)) / 3600000);
}
For short, give me the offset now and in 182 days
Executed September 3rd, the output is
EST now=-5 / +182=-5
EDT now=0 / +182=0
America/New_York now=-4 / +182=-4
This is unexpected for several reasons
1) Why is America/New_York not giving -4/-5 ?, Isn't it supposed to be date sensitive?
2) Why does EDT == UTC?
java.time
The question and the accepted answer use the java.util date-time API which was the right thing to do in 2012. In March 2014, the modern Date-Time API was released as part of the Java 8 standard library which supplanted the legacy date-time API and since then it is strongly recommended to switch to java.time, the modern date-time API.
Solution using java.time
You can use ZonedDateTime which automatically adjusts the time zone offset for a given ZoneId.
Demo:
import java.time.ZoneId;
import java.time.ZonedDateTime;
class Main {
public static void main(String[] args) {
ZoneId zone = ZoneId.of("America/New_York");
ZonedDateTime now = ZonedDateTime.now(zone);
ZonedDateTime after182Days = now.plusDays(182);
System.out.println(zone + " now=" + now.getOffset() + " / +182=" + after182Days.getOffset());
}
}
Output as of now:
America/New_York now=-05:00 / +182=-04:00
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
Do not use three-letter timezone ID: Note from the Java 7 Timezone documentation:
Three-letter time zone IDs
For compatibility with JDK 1.1.x, some other three-letter time zone IDs (such as "PST", "CTT", "AST") are
also supported. However, their use is deprecated because the same
abbreviation is often used for multiple time zones (for example, "CST"
could be U.S. "Central Standard Time" and "China Standard Time"), and
the Java platform can then only recognize one of them.
One problem you have is that 182 * 86400000 overflows. If you use
long now = System.currentTimeMillis();
for( String tzID: "EST,EDT,America/New_York".split(",")) {
TimeZone tz = TimeZone.getTimeZone( tzID);
System.out.println( tz.getDisplayName() + " now=" + tz.getOffset( now) / 36e5
+ " / +182=" + tz.getOffset( now + 182 * 86400000L) / 36e5);
}
prints
Eastern Standard Time now=-5.0 / +182=-5.0
Greenwich Mean Time now=0.0 / +182=0.0
Eastern Standard Time now=-4.0 / +182=-5.0
If you look at the javadoc and source for getTimeZone you can see
* #return the specified <code>TimeZone</code>, or the GMT zone if the given ID
* cannot be understood.
public static synchronized TimeZone getTimeZone(String ID) {
return getTimeZone(ID, true);
}
private static TimeZone getTimeZone(String ID, boolean fallback) {
TimeZone tz = ZoneInfo.getTimeZone(ID);
if (tz == null) {
tz = parseCustomTimeZone(ID);
if (tz == null && fallback) {
tz = new ZoneInfo(GMT_ID, 0);
}
}
return tz;
}
In short, EDT is not recognised so it becomes GMT.
I suspect this is the problem:
now + ( 182 * 86400000)
The parenthesized arithmetic expression overflows 32 bits. You probably want:
now + ( 182 * 86400000L)
However, that still assumes that any daylight saving time will be applied for roughly six months, which is certainly not the case in the real world. For example, looking at the Sao Paolo time zone, it switches in October and February - so if you ran your code in September, you'd end up seeing -3 / -3. Even for time zones where DST switches on/off roughly every six months, you're very likely to find 182 consecutive days each year without a switchover (almost by definition, given that that's slightly less than half a year).
It's not clear exactly what you're trying to do, but I suspect you should really just be saving the time zone ID, e.g. "America/New_York". Almost anything else is asking for trouble.

Categories