15

For some systems, the time value 9999-12-31 is used as the "end of time" as the end of the time that the computer can calculate. But what if it changes? Wouldn't it be better to define this time as a builtin variable?

In C and other programming languages there usually is a variable such as MAX_INT or similar to get the largest value an integer could have. Why is there not a similar function for MAX_TIME i.e. set the variable to the "end of time" which for many systems usually is 9999-12-31. To avoid the problem of hardcoding to a wrong year (9999) could these systems introduce a variable for the "end of time"?

**Real example **

End of validity date: 31/12/9999. (official documents are listed like this) The blogger wants to write a page that is always on top, the welcome page. So it's given a date as far in the future as possible:

3000? Yes, the welcome page which you're facing is posted at 1 January 3000. So this page will be kept on the top of the blog forever =) It's actually posted at 31 august 2007.

gnat
  • 21,442
  • 29
  • 112
  • 288
Niklas Rosencrantz
  • 8,008
  • 17
  • 56
  • 95
  • 6
    Why? This seems like problem that could be solved by implementing correct algorithm or data structure. – Euphoric Sep 14 '12 at 07:15
  • 16
    I guess most people aren't much worried about the Y10K problem yet :-) Especially as before that we are bound to have a [Y2038 problem](http://en.wikipedia.org/wiki/Year_2038_problem), and probably a couple more... – Péter Török Sep 14 '12 at 07:20
  • @PéterTörök it is my understanding that the 32->64 bit migration handles this. The amount of 32 bit systems in 2038 will - from the current trend - be rather few. –  Sep 14 '12 at 07:46
  • 2
    @Thorbjörn, yes, probably most live systems will have been migrated by then. Nevertheless, there still may be a currently inestimable amount of old embedded systems, legacy databases, files in obsolete file formats etc. – Péter Török Sep 14 '12 at 07:51
  • 2
    In the program I'm currently working with, there is a constant INFINITY with a value of 4012-12-31. Don't ask... – user281377 Sep 14 '12 at 07:55
  • Maybe slightly of interest: [How do I reset the time on my computer without turning it on?](http://superuser.com/q/473464) – George Duckett Sep 14 '12 at 08:39
  • 14
    I think the Mayan calender has an "end of time" constant = 2012-12-21 ;-) – nikie Sep 14 '12 at 11:35
  • 2
    What *immediate* problem are you trying to solve? – Jim G. Sep 14 '12 at 13:11
  • 1
    @nikie I don't know if you're joking, but it's just that they didn't bother calculating for the times ahead: it's a lot of work. Otherwise you might as well consider XXXX-12-31 the end of time, since on my calendar there's no further date. – K.Steff Sep 14 '12 at 13:28
  • 2
    @PéterTörök [rfc2550](http://tools.ietf.org/html/rfc2550) has a proposal for how to deal with y10k and beyond (yes, I am aware of the publication date of that rfc). More seriously, the Long Now organization is trying to get people to think about that timescale. –  Sep 14 '12 at 13:56
  • 1
    In C that constant is named MAX_LONG. – Jon Strayer Sep 14 '12 at 19:54
  • 1
    A choice consistent with other limits would be "beginning of time minus one". – Patrick Sep 15 '12 at 08:53
  • 1
    The [boost date time library](http://www.boost.org/doc/libs/1_51_0/doc/html/date_time/details.html#special_value_handling) has special values for both positive and negative infinities. – han Sep 16 '12 at 17:32
  • 3
    Nobody knows when "end of time" will be. – Tulains Córdova Sep 17 '12 at 13:43
  • 1
    Why don't you just use the defined max value that is going to handle a concept of a time in the given language. This will allow that value to change as the language is updated. If time is based on the number of seconds from a certain date ( in many cases ) the current max value is large enough, until the current max value is increased by using a different value type. – Ramhound Oct 10 '12 at 14:30
  • @JimG.I updated the question with an example I just saw. A blogger wants to write a welcome page. – Niklas Rosencrantz Mar 07 '13 at 22:58
  • 1
    @JonStrayer: No, `long` and `time_t` are not necessarily the same type. – Keith Thompson Mar 07 '13 at 23:02
  • 1
    @Keith True, mine was a somewhat facetious answer. – Jon Strayer Mar 11 '13 at 14:50
  • 1
    @user1249 "_The amount of 32 bit systems in 2038 will - from the current trend - be rather few._" ROTFLMAO. FORTRAN, LISP, COBOL, mainframes, OS/2, WINDOWS 3.1, _et al._ are all now decades past their predicted end-of-life and going strong. If there's **anything** this business has taught us, it's that everything will last longer than we expect. – Ross Patterson Jun 15 '14 at 20:04

7 Answers7

49

Ask yourself why you need such a variable in the first place.

Most likely, you are lying about your data: whenever you need an "end of time" variable, you are not referring to the actual end of time; rather you are expressing things like "there is no upper bound for this date", "this event continues indefinitely", or similar.

The correct solution, then, is to express these intents directly instead of relying on a magic value: use nullable date types (where null indicates "no end date set"), add an "indefinite" boolean field, use a polymorphic wrapper (which can be either a real date or a special "indefinite" value), or whatever your programming language has to offer.

Of course, the correct solution is not always feasible, so you might end up using a magic value after all, but when you do, you have to decide on a suitable value on a per-case basis, because which dates do and do not make sense depends on the domain you're modelling - if you're storing log timestamps, 01/01/2999 is a reasonable "end of time"; the chances of your application still being used almost 1000 years from now are, I would reckon, practically zero. Similar considerations go for calendar applications. But what if your software is to handle scientific data, say, long-term predictions about the Earth's climate? Those might actually want to look a thousand years into the future. Or take it one step further; astronomy, a field where it is perfectly normal to reason in very large timespans on the order of billions of years, both into the path and the future. For those, 01/01/2999 is a perfectly ridiculous arbitrary maximum. OTOH, a calendar system that is able to handle timespans ten trillion years into the future is hardly practical for a dentist appointment tracking system, if only because of storage capacity.

In other words, there is no single best choice for a value that is wrong and arbitrary by definition to begin with. This is why it is really uncommon to see one defined in any programming language; those that do usually don't name it "end of time", but rather something like DATE_MAX (or Date.MAX), and take it to mean "the largest value that can be stored in the date datatype", not "the end of time" or "indefinitely".

tdammers
  • 52,406
  • 14
  • 106
  • 154
  • 21
    using null to mean a special value isn't really any better than using that special value – Ryathal Sep 14 '12 at 12:57
  • 3
    @Ryathal Well, I think there's no 'nullenium' bug, so it's at least a bit better... – K.Steff Sep 14 '12 at 13:29
  • 9
    @Ryathal : actually it's not. There are a lot of actions you can perform on a magic number that you can't perform on null. – Pieter B Sep 14 '12 at 13:29
  • 22
    @Ryathal - `null` in this case isn't being used as a special value, it's being used as the correct meaning of `null`, which is "missing". So if your field is `ExpiryDate`, which is more correct: `null` (meaning no expiry date) or `END_OF_TIME` (which doesn't exist, as far as we know). Clearly `null` or `NoValue` or something similar is the better solution. – Scott Whitlock Sep 14 '12 at 16:33
  • 1
    @PeterB - and that is precisely why `null` is better in than a magic number. It avoids the insidious harm of `END_OF_TIME - now` by failing fast with an null pointer exception. This assumes that the language supports `null` ... – Stephen C Sep 15 '12 at 05:37
  • Thank you for the answer. I will doublecheck whether IBM really uses 9999-12-31 in DB2 as "end of time" and why the lecturer brought up that 9999-12-31 was needed in the first place. I understand the question might be difficult to understand but I was just given that 9999-12-31 is an actual date that is used for something that might have been moved as an event that is scheduled to happen but never will take place or something similar. This was on the slides in a talk that an IBM DB2 guy gave a course on and I'm positive that the date 9999-12-31 was used and immediately saw a problem with that. – Niklas Rosencrantz Oct 04 '12 at 22:31
  • @Ryathal At database level, it'd be a value that's not set, not a value that's set to NULL. Most programming languages don't understand that and make no distinction between null and not set, using null for both. – jwenting Oct 10 '12 at 14:27
  • 4
    @jwenting - They make no distinction because there isn't one. NULL means it does not exist or in more human terms the value is simply not defined. – Ramhound Oct 10 '12 at 14:35
  • @jwenting its the database making the mistake assuming null means not set. programming languages understand null just fine, it means nothing and only nothing. – Ryathal Oct 10 '12 at 15:16
  • 1
    There's a reason why IEEE754 has NaN and INF. For any finite `x`, `x – MSalters Oct 10 '12 at 16:28
  • Even your 01/01/2999 date isn't long enough to cover current events. Not long ago I ran into: http://longplayer.org/ A 1000 year long piece of music, now playing. It's going to end in 3009. – Loren Pechtel Mar 08 '13 at 05:59
  • @StephenC That's not a great argument for using null. What if you have something like completion date and when you sort you expect the items not completed to sort to the end, if you sort by completion asc? To do the sort you'll need to know if null should be considered greater or less than actual values; in the case choosing a magic number is an appropriate way to go. – Andy Dec 30 '14 at 15:01
  • @Andy - Obviously, if `null` means "end of time" then the Comparator should treat `null` as greater than all real dates. That is easy to code. Similarly, if it means "no time set", then the Comparator *could* be coded to give an NPE ... or sort null to the beginning or the ends ... depending on what the application requires. Indeed, when you think about it, you have *more* flexibility than if you are using a "special" integer or string date value ... because that special value could also be a real date. – Stephen C Dec 31 '14 at 02:19
  • @StephenC it depends heavily on the use case. A work order system would almost certainly never need to allow a date in the year 4000, and so using something like .nets DateTime.MaxValue would be appropriate and would not require any special coding except on the class that represents a work order, no custom comparer classes required. You can even let the db do the sorting with no special code. My point is that sometimes null is the right answer and sometimes a magic number is, and a blanket always do X is not good advice, it really depends on the use case. – Andy Dec 31 '14 at 02:37
17

As an industry we have been notoriously short-sighted and arbitrary in the pursuit of saving a few bytes e.g.

  • 31 Dec 99
  • January 19 2038
  • T + 50 years, when hopefully all systems I've been involved in have become defunct or been replaced (or I'm dead, whichever comes first).

IMHO the best bet is to stay with a appropriate, mainstream level of abstraction on 'max date', and hope that a common solution has addressed the issue before the time arrives.

e.g. in .NET, DateTime.MaxValue is arbitrarily 23:59:59.9999999, December 31, 9999, exactly one 100-nanosecond tick before 00:00:00, January 1, 10000. So if my assumptions about my own longevity are false, and the year 10000 arrives, I'm rather hoping that a recompile of my app with a later version of the framework will extend DateTime.MaxValue ( e.g by changing its underlying type) to a new arbitrary value and kick the problem further down the road for another few millennia.

Edit

(Reinforcing tdammers' point that rather than fudging an artificial date, that it is more correct to explicitly highlight the fact to the consumer that we don't have an end date.)

As an alternative to using null, which has the negative consequence of being type compatible with any reference type (including .Net Nullable`), which will likely cause NRE issues in consumers who forget to check, in FP languages, it is commonplace to use an Option or Maybe Type wrapper around a value which may, or may not be returned.

Pseudo code:

Option<DateTime> LeaseExpiryDate(Home rental) 
{
    if (... expiry date can be determined ...)
       return Some(rental.ExpiryDate);
    else
       return None;
}

The benefit of doing this is that it forces the consumer to reason over both cases. Pattern matching is also commonplace here:

LeaseExpiryDate(myHome) match {
     case Some(expiryDate) => "Expired"
     case None => "No Expiry"
}
StuartLC
  • 1,246
  • 8
  • 14
  • Duh. Me blind. Nevermind. – ott-- Mar 08 '13 at 15:22
  • Someday, perhaps. we'll have a [William Kahan](https://en.wikipedia.org/wiki/William_Kahan) for dates and times. The we'll have things like positively and negatively infinite timestamps, "`NaT`" values, _etc._ – Ross Patterson Jun 15 '14 at 20:13
  • 4
    Couldn't help but be reminded of this: http://www.exit109.com/~ghealton/y2k/y2k_humor/Cobol.html – Julia Hayward Jul 29 '14 at 10:20
7

You probably want an algebraic data type with variant for infinite big date. Then define comparison, in which infinite variant will be always bigger than any other date.

Example in Scala:

sealed abstract class SmartTime extends Ordered[SmartTime] { x =>
        def compare(y: SmartTime) = {
                x match {
                        case InfiniteFuture => 1
                        case InfinitePast => -1
                        case ConcreteTime(x) =>
                                y match {
                                        case InfiniteFuture => -1
                                        case InfinitePast => 1
                                        case ConcreteTime(y) => x compare y
                                }
                }
        }
}
case class ConcreteTime(t: Long) extends SmartTime
case object InfiniteFuture extends SmartTime
case object InfinitePast extends SmartTime

http://ideone.com/K5Kuk

CodesInChaos
  • 5,697
  • 4
  • 19
  • 26
Display Name
  • 265
  • 1
  • 10
2

Store your times as a 64 bits IEE754 double precision floating point number, and you can use +INF. Don't use single-precision, that's only accurate to 7 digits which is a bit low for a date.

MSalters
  • 8,692
  • 1
  • 20
  • 32
1

Cocoa/Objective-C has factory methods [NSDate distantPast] and [NSDate distantFuture] that represent exactly the kind of thing you're referring to.

The values returned by the current implementation are constants representing circa 0 AD and 4000 AD, although these aren't guaranteed or documented.

grahamparks
  • 2,099
  • 1
  • 15
  • 14
0

There generally isn't such a value, because it would not be useful as a language construct.

MAX_INT and it's kin all serve a purpose. They can be used in your code to check against overflows. This is useful if you're going to be creating and managing large data objects in arrays, vectors, whatever. It's also a fairly platform-specific value.

The use case for a MAX_DATE value is more difficult to see. Typically these are just values, they're not used as part of the structure of the program, and so the value circling around wouldn't have disastorous consequences to the program (though it may to the data). Also, the date and time types in C, C++ etc. are usually more strictly defined; and so the people writing the program don't have to worry that it may change between platforms.

TZHX
  • 5,052
  • 2
  • 25
  • 32
0

On one project that we did, we had a situation where the sizing of some database was done in a way that would not be sustainable after 30 years of using the software. When the client asked our lead engineer at the time: "Well, what are we going to do after 30 years of using your software?" Our lead engineer, cool as a cucumber, replied with a shrug: "We'll go and have a beer!"

The point is, just use the date that is far enough in the future. Chances are your software will be upgraded or replaced by then. :)

Vladimir Stokic
  • 2,943
  • 14
  • 25