1

I need to create a unique ID or reference number that's based on the current time format yymmddHHmmss + (sequence 0-9). I know about UUID but I prefer this instead. Can someone show me how to do it in Java? Thanks.

Master EZ
  • 47
  • 4
  • 1
    Does this help? https://docs.oracle.com/javase/tutorial/datetime/index.html – Abra Apr 21 '21 at 12:11
  • Didn’t you ask the same question just a few days ago? – Ole V.V. Apr 21 '21 at 16:39
  • If you really want a universally unique identifier, you really should be using a [Universally Unique Identifier (UUID)](https://en.m.wikipedia.org/wiki/Universally_unique_identifier). Using UUIDs avoids the problematic circumstances mentioned in the correct [Answer by Ole V.V.](https://stackoverflow.com/a/67200285/642706). And UUIDs handle many more sequence numbers per fraction of a second than your granularity of ten per second. And UUIDs are standard, easily recognized and understood by skilled programmers and sysadmins, and interoperable with other systems. – Basil Bourque Apr 23 '21 at 07:32

2 Answers2

3

java.time

I recommend that you use java.time, the modern Java date and time API, for your date and time work. Here’s a suggestion doing so.

private static final int MIN_SEQ = 0;
private static final int MAX_SEQ = 9;
private static final DateTimeFormatter FORMATTER
        = DateTimeFormatter.ofPattern("yyMMddHHmmss");

private LocalDateTime lastTime = LocalDateTime.now(ZoneId.systemDefault())
        .minusMinutes(1); // Initialize to a time in the past
private int lastSeq = 0; // Initialize to any value

public String getUniqueId() {
    LocalDateTime time = LocalDateTime.now(ZoneId.systemDefault())
            .truncatedTo(ChronoUnit.SECONDS);
    if (time.isBefore(lastTime)) {
        throw new IllegalStateException("Time is going backward");
    }
    if (time.isAfter(lastTime)) {
        lastTime = time;
        lastSeq = MIN_SEQ;
    } else { // Still the same time
        lastSeq++;
    }
    if (lastSeq > MAX_SEQ) {
        throw new IllegalStateException("Out of sequence numbers for this time");
    }
    return lastTime.format(FORMATTER) + lastSeq;
}

It will break miserably under the following two circumstances:

  1. If used during the spring back where clocks are turned back and the same times repeat.
  2. If the time zone of your JVM is changed. Any part of your program and any other program running in the same JVM may do that at any time.

It will also give non-increasing IDs if the program happens to be running by New Year 2100. Since a LocalDateTime includes full year, it will continue running and giving IDs, though.

Why not try it out?

    for (int i = 0; i < 12; i++) {
        System.out.println(getUniqueId());
        TimeUnit.MILLISECONDS.sleep(150);
    }

In one case output was:

2104212202180
2104212202181
2104212202190
2104212202191
2104212202192
2104212202193
2104212202194
2104212202195
2104212202196
2104212202200
2104212202201
2104212202202

Link

Oracle tutorial: Date Time explaining how to use java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
2

Use simple date formatter to format the current timestamp to 'yymmddHHmmss' and use a global variable to get the sequence number for that timestamp.

private static final int MIN_SEQ = 0;
private static final int MAX_SEQ = 9;

private String lastDate = new SimpleDateFormat("yyMMddHHmmss").format(new Date());
private int lastSequence = 0;

private static String getUID()
{
    String currentDateTime = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

    if (currentDateTime.equals(lastDate))
    {
        lastSequence++;
    }
    else
    {
        lastDate = currentDateTime;
        lastSequence = MIN_SEQ;
    }

    if (lastSequence > MAX_SEQ)
    {
        throw new IllegalStateException("Sequence numbers out of range.!");
    }

    return lastDate + lastSequence;
}

Output

2104211714401
2104211714402
2104211714403
2104211714404
2104211714405
2104211714406

2104211714410
2104211714411
2104211714412
2104211714413
2104211714414
Pramod H G
  • 1,513
  • 14
  • 17
  • 1
    This works. Only, it is a sequence from 1-9 and not random. It means the first generated ID starts from 1, the second is 2 and so on... up to 10. – Master EZ Apr 21 '21 at 12:49
  • You can define a global variable with value 1 and increment the value each time after appending with the date. – Pramod H G Apr 21 '21 at 12:54
  • I use this code. Im not sure if it will increment since I can't test it. for (int i = 1 ; i <= 10; i += 10) { id = formattedDate + i; } – Master EZ Apr 21 '21 at 13:07
  • 1
    Please don’t teach the young ones to use the long outdated and notoriously troublesome `SimpleDateFormat` class. At least not as the first option. And not without any reservation. We have so much better in [`java.time`, the modern Java date and time API,](https://docs.oracle.com/javase/tutorial/datetime/) and its `DateTimeFormatter`. – Ole V.V. Apr 21 '21 at 16:40