Click here to Skip to main content
15,888,908 members
Articles / Programming Languages / C#
Tip/Trick

Simple DateTime to Julian Day and UnixTime Values

Rate me:
Please Sign up or sign in to vote.
4.71/5 (8 votes)
24 Nov 2015CPOL4 min read 16.3K   256   6   3
Four one-line methods to convert between DateTime objects and Julian Days or Unix Time Stamps

Introduction

There are a lot of systems around that keep timestamps as either UnixTime or Julian Days, whereas your C# code tends to use the System.DateTime structure for working with dates and times. Fortunately, the DateTime structure is able to help you out with these conversions, albeit these conversions are not immediately obvious.

Background

I'm currently writing a project using an SQLite database, SQLite's date functions take its formats in ISO-8601 (or derivatives thereof), or in the Julian Days or Unix Timestamp formats. The DateTime structure intrinsically handles all ISO-8601 formats fine, but I wanted to handle the other ones also.

So I started looking around for conversion methods. The best information on what these values entail, and how they are calculated, came from Wikipedia pages on Unix Time and Julian Day. Most of the solutions I found are centered around the calculations described on those pages.

Then I started to think about what those numbers are. Basically, they are simply a period of time from some arbitrary point in time way back in history.

For unix time, this is 1970-01-01 00:00:00, and the intervals used is seconds. So, to go from a DateTime to Unix time, or visa-versa, it is simply a matter calculating those seconds. DateTime has all the mathematics for adding and subtracting time periods built in, so rather than re-inventing the wheel and writing a function with all of that math, I let DateTime do it for me.

For the Julian Day, it is a little more complicated. This number represents the number of days (with the fractional part being the part of the day i.e. the time) since Midday on November 24, 4714 B.C. (if we stick to using the same calendar). Not only is calculating the actual number of days between any two days tricky, considering the differing numbers of days in each month, as well as taking into account leap years and their variants, but 4214 B.C. is well out of range of the DateTime object. But then something clicked from my old days of COM programming - the OLE date time was stored as a count of the number of days, with the fractional part representing the time, just using a relatively modern epoch. It turns out that that instant in time was Midnight on December 31, 1899. So all that is needed to calculate the Julian Day is to get that OLE number, and add it to the number of days between the Julian Day epoch and the OLE day epoch - that number turns out to be 2,415,018.5 days (which is just the Julian Day of the OLE epoch - 1). Once again, DateTime has built in methods for converting to and from the OLE number - and so there it is.

Using the Code

The functions to convert to a Unix Time and a Julian Day, I have written as an extension to the DateTime object - so they can be called just like any other method on this object. To get the current time as a Unix Time or Julian day, simply:

C#
DateTime dt = DateTime.Now;
double UnixTime = dt.ToUnixTime;
double JulianDay = dt.ToJulianDay;

Going the other way is not quite as simple, as it is not possible to create static object extensions - and a static method to create a DateTime object is what is needed. Therefore, I have simply written plain static functions contained within the extensions class.

C#
DateTime myBirthday = DateTimeExtensions.FromJulianDay(2437249D);
DateTime myBirthdayThisYear = DateTimeExtensions.FromUnixTime(1447156800D);

Points of Interest

This was a lot of talk on the Wikipedia page about taking into account leap-seconds. I don't believe the DateTime object takes these into account, which means that the calculations here do not either. This means that the UnixTime values may be up to 26 seconds out (that's how many leap-seconds we've had since the Unix Epoch). I guess it would be feasible to set up a table to add in these leap-seconds when they occurred, but (a) that would make the UnixTime and the DateTime object slightly out-of sync, and if Microsoft does eventually take them into account, then the code would break in the other direction, and (b) a maximum of 26 seconds of error will not kill my real-world applications, providing I know about it.

I made the time element in the second example above equal to midday, simply because I like to sleep in on my birthday.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Australia Australia
Been programming for 40 years now, starting when I was 13 on DEC PDP 11 (back in the day of paper tape storage, and hex switch boot procedures). Got right into micro-computers from an early age, with machines like the Dick Smith Sorcerer and the CompuColor II. Started CP/M and MS-DOS programming in the mid 1980's. By the end of the '80's, I was just starting to get a good grip on OOP (Had Zortech C++ V1.0).

Got into ATL and COM programming early 2002. As a result, my gutter vocabulary has expanded, but it certainly keeps me off the streets.

Recently, I have had to stop working full time as a programmer due to permanent brain damage as a result of a tumour (I just can't keep up the pace required to meet KPI's). I still like to keep my hand in it, though, and will probably post more articles here as I discover various tricky things.

Comments and Discussions

 
QuestionImprovement Pin
W. Kleinschmit25-Nov-15 13:14
W. Kleinschmit25-Nov-15 13:14 
AnswerRe: Improvement Pin
Midi_Mick25-Nov-15 15:05
professionalMidi_Mick25-Nov-15 15:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.