1

I'm using the current date and time to generate a unique folder name. Are there any likely scenarios in which a clash could happen? I think not, since, down to the millisecond, no two dates can be the same (unless two uploads happen at the same millisecond--but this is not likely in my current scenario).

(Time.now.to_f * 1000).to_i
Jumbalaya Wanton
  • 1,601
  • 1
  • 25
  • 47
  • 1
    Well, then, if two *can*, then it's entirely possible, right? At that point it stops being impossible, and becomes, at best, unlikely. And, as programmers, we have to think ahead and program for those unlikely events and what we'll do in such a case. – the Tin Man Jan 02 '14 at 16:22
  • But other than that, can they? – Jumbalaya Wanton Jan 02 '14 at 16:22
  • 2
    Of course they can. That's the point. Don't rely on a timestamp to ensure uniqueness. – the Tin Man Jan 02 '14 at 16:24
  • Any given date (to the millisecond) will be unique to that date. If there's a possibility that two uploads could happen at the same time and you want them separated, you'll have to modify your naming scheme. If you append a random int to the name, that will reduce the likelihood of a clash, even if two uploads occur at the exact same time, to, say, 1 in a billion (or whatever size random you choose). – Reinstate Monica -- notmaynard Jan 02 '14 at 16:25
  • ... You already know the answer to that, and fixing it is as easy as appending a guid. – Dave Newton Jan 02 '14 at 16:26
  • I really don't see the possibility that my application would be so popular as to have two uploads at identical times. Thank you for the vote of confidence, though. I hope you are right. I was just looking for something obvious that I could have missed. – Jumbalaya Wanton Jan 02 '14 at 16:26
  • Imagine the case of Facebook; With sufficient numbers of users, or uses, your odds of timestamp collisions goes WAY up. – the Tin Man Jan 02 '14 at 16:30
  • 5
    You application doesn't have to be popular for the same time stamp to be applied to two uploads. Its just has to be unlucky. – Wayne Conrad Jan 02 '14 at 16:40
  • 2
    You don't even need bad luck. It's not unheard of for users to accidentally double click a button. A single such user will mess up your scheme. – gspr Jan 02 '14 at 17:31
  • @JumbalayaWanton has the answer been helpful? – Малъ Скрылевъ Jan 23 '14 at 08:49

5 Answers5

3

You probably want to use Dir.mktmpdir from the tmpdir standard library. It will handle a genuinely unique and conflict free directory name that takes system time and process id into account.

Parker Selbert
  • 1,546
  • 13
  • 13
  • You want to be VERY careful using `mktmpdir`. It creates a TEMPORARY directory. – the Tin Man Jan 02 '14 at 16:28
  • Granted, I can only assume that trying to use a timestamp for uniqueness is a temporary solution. Anything persisted long term would use a more deterministic naming scheme. A directory created with `mktmpdir` will be cleaned up whenever the associated object is garbage collected. – Parker Selbert Jan 03 '14 at 03:20
  • Not necessarily garbage collected by Ruby. It creates temporary directories in the OS's temporary space, so the OS will do it too, depending on whether the `mktmpdir` is called with a block or not. – the Tin Man Jan 03 '14 at 03:59
2

Computers generally update their clock periodically to correct drifting.

It is very possible for the clock to jump back in time, and then to get twice the same value.

Don't use time for unique values

Antzi
  • 12,831
  • 7
  • 48
  • 74
1

Quite, but the coerced time get after a millisecond of the past one differs by at least 1 (in some cases by 2) only when you multiply it to 1000 then get an integer.

pp = (Time.now.to_f * 1000).to_i; sleep 0.001 ; ppp = (Time.now.to_f * 1000).to_i
# 1388680023598
# 1388680023599

When you multiply to 10^6 you'll get another result:

pp = (Time.now.to_f * 1000000).to_i; sleep 0.001 ; ppp = (Time.now.to_f * 1000000).to_i
# 1388681046148709
# 1388681046149988

Also, if you wish to get unique name you can use UUIDs the ruby's version of GUIDs. But if you need to make unique temporary folder, you should use ruby's method to create a temp folder, as it was denoted in the earlier answer.

Community
  • 1
  • 1
Малъ Скрылевъ
  • 16,187
  • 5
  • 56
  • 69
  • As far as I can [read from the documentation](http://ruby-doc.org/core-1.9.3/Time.html) (I don't speak Ruby), `Time.now` is *real* system time. Real system time is *not* monotonic – there are no guarantees that your code won't give the same result twice even if called more than a millisecond apart! [This website I know nothing aboout](http://blog.rubybestpractices.com/posts/ewong/012-Unix-time-and-the-Time-class.html) says that no monotonic clock is exposed in the Ruby standard library. – gspr Jan 02 '14 at 16:38
  • The edit doesn't seem to rectify my objection to your answer. I meant that (if I read the documentation correctly) `Time.now` itself can run backwards, or quickly forwards, or slowly forwards, or stay the same, between any two points in time (nomatter how far apart in actual time these points are). It reflects *real system time*, which can change arbitrarily. We (and the others who have answered) clearly agree that time is a stupid way to do what OP wants, but my downvote reflects that I highly disagree with the statement about time "differing by 1". – gspr Jan 02 '14 at 17:21
  • @gspr Since the coerciong was presented in the qustion I answered to it, but I've added an ajective which describes the it isn't real time – Малъ Скрылевъ Jan 02 '14 at 17:24
  • It doesn't matter what you multiply `Time.now` with. There are *no guarantees that any two calls/inspections will differ by 1 nomatter how carefully you orchestrate the wait*. You seem to claim there is. What I'm saying is that in `t0 = Time.now.to_f; sleep dt; t1 = Time.now.to_f;`, `t1` may be the same as, or even smaller than, `t0` *nomatter what `dt` is*. – gspr Jan 02 '14 at 17:26
  • @gspr I've never guaranteed that a two call will differ by 1 – Малъ Скрылевъ Jan 02 '14 at 17:47
1

I think not, since, down to the millisecond, no two dates can be the same

You're assuming that when you get the time from your system clock that you have millisecond resolution. Even though you're getting a number of milliseconds, it does not mean that the hardware has a 1 millisecond resolution.

With most modern computers and operating systems, it's closer to 10 milliseconds. If you anticipate a high volume of calls, you certainly could read the time several milliseconds close together and they could get the same exact timestamp.

You'd be better off appending an auto-incrementing integer, or some random number or guid. If you wanted some sortability, you could add a timetamp and another number.

Also, you should keep in mind that the user can adjust the clock at any time, or it might change on its own if the system is synchronized by NTP.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
0

You can avoid the problem entirely just by putting a little bit of extra effort so why not do that right away?

I can see two solutions:

  1. Name the directories using consecutive numbers. When creating it, you need to list existing directories, find the one with the highest number, and try to create a directory with this number + 1. It may fail in case of a race condition that's why you should retry it (Ruby's retry statement might be a perfect match for this case).
  2. Name the directories with UUIDs. Again, you may run into conflict too so you need to retry your attempt if the directory already exists.
Greg Navis
  • 2,818
  • 10
  • 10