A stardate is a fictional system of time measurement developed for the television and film series Star Trek. In the series, use of this data system is commonly heard at the beginning of a voice-over log entry.
While the general idea resembles the Julian day1 currently used by astronomers, writers and producers have selected numbers using different methods over the years, some more arbitrary than others. This makes it impossible to convert all stardates into equivalent calendar dates, especially since stardates were originally intended to disguise the precise era of Star Trek. The following excerpt from the Star Trek Guide (April 17, 1967, p. 25) instructs writers for the original Star Trek TV series2 on how to select stardates for their scripts.
We invented "Stardate" to avoid continually mentioning Star Trek's century (actually, about two hundred years from now), and getting into arguments about whether this or that would have developed by then. Pick any combination of four numbers plus a percentage point, use it as your story's stardate. For example, 1313.5 is twelve o'clock noon of one day and 1314.5 would be noon of the next day. Each percentage point is roughly equivalent to one-tenth of one day. The progression of stardates in your script should remain constant but don't worry about whether or not there is a progression from other scripts. Stardates are a mathematical formula which varies depending on location in the galaxy, velocity of travel, and other factors, can vary widely from episode to episode.
According to creator Gene Roddenberry3, the stardate has initially been devised to prevent that events in the television series could be pinpointed to a specific year. He gave the following explanation about this:
"This time system adjusts for shifts in relative time which occur due to the vessel's speed and space warp capability. It has little relationship to Earth's time as we know it. One hour aboard the USS Enterprise at different times may equal as little as three Earth hours. The stardates specified in the log entry must be computed against the speed of the vessel, the space warp, and its position within our galaxy, in order to give a meaningful reading."
Roddenberry later told that he did not fully understand this explanation himself, but that others considered it a logical explanation:
"I'm not quite sure what I meant by that explanation, but a lot of people have indicated it makes sense. If so, I've been lucky again, and I'd just as soon forget the whole thing before I'm asked any further questions about it."
Because there's no clear reasoning behind the stardate, throughout the series and films several examples of events are found that happen later in time but have a lower stardate than something that happened earlier.
We will use two different methods to express dates in our era as stardates. The old method roughly corresponds to the stardates used in the first six Star Trek motion pictures. The method represents a date in our era in the format YYMM.DD, where YY corresponds to the year minus 1900, MM to the month (01-12) and DD to the day of the month (01-31). The values are always expressed with two digits, using a leading zero if necessary. As a result, September 8, 1966 is represented using the old method as stardate 6609.08. Another digit must be added for years after 1999, such that September 11, 2015 is represented using the old method as stardate 11509.11.
Starting from the motion picture Star Trek XI4 a new method was used to convert dates from our era into stardates. Following this new method, stardates are expressed in the format YYYY.xx, where YYYY is the actual four-digit year, and .xx expresses the fraction of the year that has passed to two decimal places (i.e., hundredths of a year). The last to digits may thus be determined by calculating the number of days since January 1 of the given year (no days have passed on January 1, one day has passed on January 2, and so on) times one hundred and dividing this result by the total number of days in the year (taking into account leap years). If the decimal places are left out, this results in an integer between 0 and 99 (including the boundaries). As a result, January 1, 2015 corresponds to stardate 2015.00 and July 4, 2015 to stardate 2015.50 (halfway through the year 2015).
Define a class Stardate that can be used to represent stardates in Python. This class must at least support the following methods:
An initialization method that takes a date (datetime.date) as its argument. The given data represents the date from our era that corresponds with the stardate represented by the object. In case no date is passed to the initialization method, the object represents that stardate that corresponds to the current date.
A method __repr__ that returns a string representation (str) of the stardate, corresponding the Python statement that can be used to create a stardate (Stardate) that is equivalent with the current object. This representation must be formatted as Stardate(date), where date is the string representation of the corresponding date from our era that is returned from the built-in function repr.
A method that __str__ returns a string representation (str) of the stardate that either corresponds to the representation according to the old method or the new method as described above (also see the description of the method switch below). Immediately after initialization of the object, a representation according to the new method must be returned.
A method switch that takes no arguments. If this method is called, the method __str__ should switch between the old method and the new method for the representation of the stardate. This means that if the old method was used before calling the method switch, the new method must be used after calling it, and vice versa.
>>> import datetime
>>> date = Stardate(datetime.date(2015, 9, 11))
>>> repr(date)
'Stardate(datetime.date(2015, 9, 11))'
>>> date
Stardate(datetime.date(2015, 9, 11))
>>> str(date)
'2015.69'
>>> print(date)
2015.69
>>> date.switch()
>>> date
Stardate(datetime.date(2015, 9, 11))
>>> print(date)
11509.11
>>> date.switch()
>>> date
Stardate(datetime.date(2015, 9, 11))
>>> print(date)
2015.69
>>> today = Stardate()
>>> today
Stardate(datetime.date(????, ??, ??))
>>> print(today)
????.??
>>> print(Stardate(datetime.date(2015, 1, 1)))
2015.00
>>> print(Stardate(datetime.date(2015, 7, 4)))
2015.50
>>> print(Stardate(datetime.date(2015, 7, 5)))
2015.50
>>> print(Stardate(datetime.date(2015, 7, 6)))
2015.50
>>> print(Stardate(datetime.date(2015, 7, 7)))
2015.51
>>> print(Stardate(datetime.date(2015, 12, 31)))
2015.99