tags:

views:

387

answers:

8

What is the best way to retrieve the current date? Currently I am storing the date like this:

string date = DateTime.Now.ToString("yyyyMMdd");

Obviously, if the user changes the date on their system, this will also be affected.

I need a way to access an accurate date (preferable in central time) and store it as a string within my application. Any ideas?

A: 

Always store in UTC time - you'll save yourself a load of trouble later on. Store in UTC and convert to whatever local time you need, including daylight saving time, at the time you need it for your calculation.

Also, if the time doesn't need to be human readable in storage, you could store it in Ticks to be least error-prone:

string ticks = DateTimeOffset.UtcNow.Ticks.ToString();

DateTimeOffset stampUtc = new DateTimeOffset(long.Parse(ticks), TimeSpan.Zero);

DateTimeOffset stampLocal = stampUtc.ToLocalTime();

uosɐſ
Wouldn't using DateTimeOffset still rely on the system date/time?
Nate Shoffner
Yes. I think I read emphasis on the wrong part of your question. What are you trying to protect against? Are you trying to detect any change to the system time? Are you trying to not let them change the time backward to get around a time-trial?
uosɐſ
If you are always connected, why don't you ask your central server for the time instead of relying on the local system time?
uosɐſ
I am just trying to get the date, from a trusted source. Obviously trusting the users system is out of the question. All I need is to retrieve the date in a "YYYYMMDD" format.
Nate Shoffner
So do you trust your own server, the one that the users have to connect to anyway, as you've said? Add service method, or however it connects, called GetCurrentServerTimeUTC(). Why isn't this acceptable?
uosɐſ
+4  A: 

Define "accurate"? If you cannot trust the system date, then you need to get the time from an outside source (ie, atomic clock). But the user may block your program from getting it (ie, unplugging the network cable, blocking your time query with a software firewall).

So what is it that you really want?

gmagana
Well the application needs a network connection since it connects to online resources. Without one the application would be useless haha. The users already know that.
Nate Shoffner
Depending on what those resources are, you might get the date that way. If it is a web service (or app server, or similar) under your control that is the connection target, just get the date from the service. If not, get time date from an atomic clock somewhere.
gmagana
+1  A: 

You could implement a very simple web service or RESTful call on a server that would provide the result. This would work as long as you trusted that the server's date/time were correct.

Mike Hodnick
+2  A: 

Whatever date/time you get locally, depends on the current system's time accuracy. If you want independent accurate time, you'll need to get it externally from a time web service like Yahoo's Server Time.

Traveling Tech Guy
+2  A: 

EDIT: This works, give it a try:

private string GetCurrentDateTime()
{
    WebRequest request = WebRequest.Create(@"http://developer.yahooapis.com/TimeService/V1/getTime?appid=Test");
    // request.Proxy = new WebProxy("PROXYSERVERNAME", 8080); // You may or may not need this
    WebResponse response = request.GetResponse();      

    Double currentTimeStamp = 0;
    using (Stream stream = response.GetResponseStream())
    {
        using (XmlTextReader xmlReader = new XmlTextReader(stream))
        {
            while (xmlReader.Read())
            {
                switch (xmlReader.NodeType)
                {
                    case XmlNodeType.Element:
                        if (xmlReader.Name == "Timestamp")
                        {
                            currentTimeStamp = Convert.ToDouble(xmlReader.ReadInnerXml());
                        }
                        break;
                }
            }

            xmlReader.Close();
        }
    }

    DateTime yahooDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
    return yahooDateTime.AddSeconds(currentTimeStamp).AddHours(2).ToString("yyyyMMdd");     
}
Philip Wallace
Wouldn't this still be relying on the system date?
Nate Shoffner
@Nate - yes. I found a sample which gets the time from Yahoo instead.
Philip Wallace
I tried downloading the source and it's empty? Also, it says it says it synchronizes the users system time. Is that all really necessary? Is there just a simple way to retrieve the date from a webservice and store it as a string?
Nate Shoffner
The source is all listed on the page. Also, look at the part that connects to the web and gets the time, ignore the rest.
Philip Wallace
Answer updated with a sample... it works, I tried it.
Philip Wallace
Ok, I've never done anything like this. Do I need to keep the proxy portion in there? And where is the actual string that has the date stored?
Nate Shoffner
If you are not on a corporate network that uses a proxy, then you most likely don't need that line. The method returns a DateTime... you can get the string from there.
Philip Wallace
Sorry haha. Ok got it working. Just wondering, is there a way to make it display Central time? It's currently displaying PST. Also, is there a way to trim it down to only the date. Don't really need the time. I'm sorry if I'm being a pain, but I have no idea what to do here lol.
Nate Shoffner
You mean CST? Try this:yahooDateTime.AddSeconds(currentTimeStamp).AddHours(2).ToString("yyyyMMdd");
Philip Wallace
Thanks, but it shows an error saying "Cannot implicitly convert type 'string' to 'System.DateTime'"
Nate Shoffner
Look at the sample in the answer. You have to change the return type of the method to string.
Philip Wallace
Thank you so much. You really didn't have to do all this for me haha. I really appreciate it!
Nate Shoffner
+1  A: 

Since the user can change the time on the bios you can't trust that the computer will be accurate.

Your only other choice requires that they have access to the Internet, then you can call out to a webservice, and make a call, but if you are going to be paranoid, and to limit how much they know is going on, encrypt it with RSA encryption, to verify that your service gave the date.

James Black
Not worried about encryption or anything like that. Just need an accurate date that doesn't rely on the system (webservice as you said). Any recommendations?
Nate Shoffner
You should write your own, to ensure that it is accurate for all applications, but here is some brief discussion about time webservices: http://weblogs.asp.net/jgalloway/archive/2004/04/08/110029.aspx
James Black
A: 

If you need to capture the current time and don't want to be coupled to the machine the code is running on having a correct date/time set, you can use NTP to retrieve the current time from the network (or internet) ... assuming the machine is actively connected to one.

I believe the US Navy maintains a group of NTP servers. Check out: http://tycho.usno.navy.mil/ntp.html

If you need super-secure, highly resilient access to the current time, you're going to need to have some level of control over the hardware you're running on. After all, users can pull their network cable, spoof IP addresses on a network, block ports and IP addresses, change their HOSTS file, all sorts of things that could interfere with a network request for the time.

LBushkin
A: 

This is an old problem. I believe you're looking for NTP (Network Time Protocol). Browse around http://time.gov/about.html and you can find a public server that will give you the standard time.

Also, to use NTP, you may want to look at this. http://stackoverflow.com/questions/1193955/how-to-query-an-ntp-server-from-c

Matt Brunell