fortm
fortm

Reputation: 4198

Generate different date for each iteration

Here needed to generate different values for Date in each iteration of for loop.

Using currentTimeMillis does not help as it gives same time but nanoTime gives wrong date altogether.

    for (int i = 0; i < 10; i++) {
        System.out.println(new Date(System.currentTimeMillis()));
    }

    for (int i = 0; i < 10; i++) {
        System.out.println(new Date(System.nanoTime()));
    }

Mon Oct 30 19:33:43 IST 2017
Mon Oct 30 19:33:43 IST 2017
Mon Oct 30 19:33:43 IST 2017
Mon Oct 30 19:33:43 IST 2017
Mon Oct 30 19:33:43 IST 2017
Mon Oct 30 19:33:43 IST 2017
Mon Oct 30 19:33:43 IST 2017
Mon Oct 30 19:33:43 IST 2017
Mon Oct 30 19:33:43 IST 2017
Mon Oct 30 19:33:43 IST 2017

Tue Feb 09 09:56:54 IST 2292
Tue Feb 09 09:57:39 IST 2292
Tue Feb 09 09:58:10 IST 2292
Tue Feb 09 09:58:50 IST 2292
Tue Feb 09 09:59:24 IST 2292
Tue Feb 09 09:59:53 IST 2292
Tue Feb 09 10:00:29 IST 2292
Tue Feb 09 10:00:59 IST 2292
Tue Feb 09 10:01:37 IST 2292
Tue Feb 09 10:02:18 IST 2292

UPDATE : Need to generate different timestamp for each iteration as that is going in cassandra database where different records need to have unique timestamp. Otherwise they will overwrite each other. Also time should not be fake as adding a second in for loop would solve the problem but is fake time.Adding sleep is unfortunately not an option as the code needs to add records as fast as possible and exit

Upvotes: 1

Views: 433

Answers (4)

Crusha K. Rool
Crusha K. Rool

Reputation: 1502

If the only requirement is that the dates are different from each other, then you can just manually increment the date by an arbitrary amount in the loop.

And in case you're using Java 8 or higher, I also recommend staying clear of the old java.util.Date API and start using java.time instead.

Instant instant = Instant.now();
for ( int i = 0; i < 10; i++ )
{
    System.out.println( instant.toString() );
    // Choose whatever interval size you need in your specific case.
    instant = instant.plus( 1, ChronoUnit.MILLIS );
}

You can still convert back to Date objects if you really need to by using Date.from( instant ).

EDIT: Seeing your updated requirements, I adjusted my answer now.

There are several limitations that you need to be aware of:

  • System clock resolution: You won't get around manually faking some dates (for example by adding a millisecond each iteration in the loop), since the resolution of the system clock is not precise enough to generate a distinct timestamp on each call.

  • Datatype of the column in your database: Databases often only have a limited precision for the date values they can store. For example Oracle's old Date datatype can only store precision up to seconds and no fractions. I believe MS SQLServer's DateTime type rounds its milliseconds to the nearest third of a second or something like that.

  • Java datatype precision: The old java.util.Date type can only store up to millisecond precision. java.time.Instant can also store nanoseconds. JDBC in Java 8 comes with matching methods that accepts Instant instead of Date, but the actual database and its JDBC driver implementation of course need to actually support that precision as well.

Upvotes: 1

phflack
phflack

Reputation: 2727

new Date(long time) gives a date based on milliseconds - it isn't that it's giving the wrong date, it's the correct date for the wrong time given

System.currentTimeMillis() gives the correct time for date, while System.nanoTime() is about 1000x the correct time (in milliseconds)

It may be easier to use new Date() over new Date(System.currentTimeMillis()), as they will both give the current time to the closest millisecond


If your goal is to get similar dates, instead try incrementing the time you're initializing the dates with (in this case 1 second differences)

long now = System.currentTimeMillis();
for(int i = 0; i < 10; i++)
    System.out.println(new Date(now + i * 1000));

Upvotes: 0

Suresh Atta
Suresh Atta

Reputation: 121998

To start with note that nano gives more value than milli and you are passing a nanoseconds value in place of milliseconds, hence the bizarre result.

What Date(long date) constructor expecting

date - the milliseconds since January 1, 1970, 00:00:00 GMT.

What nanoTime returning

Returns the current value of the running Java Virtual Machine's high-resolution time source, in nanoseconds.

The nanoTime is not at all related to Date(). It is designed and implemented to solve a different purpose.

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary origin time (perhaps in the future, so values may be negative). The same origin is used by all invocations of this method in an instance of a Java virtual machine; other virtual machine instances are likely to use a different origin.


Here needed to generate different values for Date in each iteration of for loop.

Probably you can try adding time in minutes/days to the current date by adding i value ?

Upvotes: 4

streetturtle
streetturtle

Reputation: 5850

The first code snippet is working as expected. All steps in the loop a executed at the same time. If you want different time then sleep the executing thread:

for (int i = 0; i < 10; i++) {
    System.out.println(new Date(System.currentTimeMillis()));
    Thread.sleep(1000);
}

which would give following:

Mon Oct 30 10:10:10 EDT 2017
Mon Oct 30 10:10:11 EDT 2017
Mon Oct 30 10:10:12 EDT 2017
Mon Oct 30 10:10:13 EDT 2017
Mon Oct 30 10:10:14 EDT 2017
Mon Oct 30 10:10:15 EDT 2017
Mon Oct 30 10:10:16 EDT 2017
Mon Oct 30 10:10:17 EDT 2017
Mon Oct 30 10:10:18 EDT 2017
Mon Oct 30 10:10:19 EDT 2017

The second code snippet is wrong in terms that Date is expecting millis in constructor. The nanoTime() actually should be used to get the delta, as

The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values may be negative).

Upvotes: 2

Related Questions