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.

19
  • 6
    Why? This seems like problem that could be solved by implementing correct algorithm or data structure.
    – Euphoric
    Sep 14, 2012 at 7: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, and probably a couple more... Sep 14, 2012 at 7:20
  • 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. Sep 14, 2012 at 7:51
  • 14
    I think the Mayan calender has an "end of time" constant = 2012-12-21 ;-)
    – nikie
    Sep 14, 2012 at 11:35
  • 3
    Nobody knows when "end of time" will be. Sep 17, 2012 at 13:43

7 Answers 7

49
+50

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".

14
  • 21
    using null to mean a special value isn't really any better than using that special value
    – Ryathal
    Sep 14, 2012 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, 2012 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, 2012 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. Sep 14, 2012 at 16:33
  • 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, 2012 at 14:35
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"
}
3
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

1
  • Quote the code in your answer for posterity.
    – deadly
    Oct 9, 2012 at 15:01
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.

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.

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.

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. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.