web-dev-qa-db-ja.com

インターネットからDateTimeを取得する方法は?

C#を使用してインターネットまたはサーバーから現在の日付と時刻を取得する方法は?私は次のように時間を取得しようとしています:

public static DateTime GetNetworkTime (string ntpServer)
{
    IPAddress[] address = Dns.GetHostEntry(ntpServer).AddressList;

    if (address == null || address.Length == 0)
        throw new ArgumentException("Could not resolve ip address from '" + ntpServer + "'.", "ntpServer");

    IPEndPoint ep = new IPEndPoint(address[0], 123);
    return GetNetworkTime(ep);
}

サーバーのIPアドレスをnetServerとして渡しますが、正しく機能しません。

44
hmlasnk

ポート13がブロックされている環境では、次のようにNISTからの時間をWebスクレイピングできます。

public static DateTime GetNistTime()
{
    DateTime dateTime = DateTime.MinValue;

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://nist.time.gov/actualtime.cgi?lzbc=siqm9b");
    request.Method = "GET";
    request.Accept = "text/html, application/xhtml+xml, */*";
    request.UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)";
    request.ContentType = "application/x-www-form-urlencoded";
    request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore); //No caching
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    if (response.StatusCode == HttpStatusCode.OK)
    {
        StreamReader stream = new StreamReader(response.GetResponseStream());
        string html = stream.ReadToEnd();//<timestamp time=\"1395772696469995\" delay=\"1395772696469995\"/>
        string time = Regex.Match(html, @"(?<=\btime="")[^""]*").Value;
        double milliseconds = Convert.ToInt64(time) / 1000.0;
        dateTime = new DateTime(1970, 1, 1).AddMilliseconds(milliseconds).ToLocalTime();
    }

    return dateTime;
}
55
Nemo

NISTインターネットタイムサービス から時間を取得するために使用できるコードサンプルを次に示します。

var client = new TcpClient("time.nist.gov", 13);
using (var streamReader = new StreamReader(client.GetStream()))
{
    var response = streamReader.ReadToEnd();
    var utcDateTimeString = response.Substring(7, 17);
    var localDateTime = DateTime.ParseExact(utcDateTimeString, "yy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
}
39
Alex Aza

ヘッダーから時間を取得する簡単なコードを次に示します。ポート13を使用せずに動作します

public static DateTime GetNistTime()
{
    var myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.Microsoft.com");
    var response = myHttpWebRequest.GetResponse();
    string todaysDates = response.Headers["date"];
    return DateTime.ParseExact(todaysDates, 
                               "ddd, dd MMM yyyy HH:mm:ss 'GMT'", 
                               CultureInfo.InvariantCulture.DateTimeFormat, 
                               DateTimeStyles.AssumeUniversal);
}
30
glienart

物事がうまくいかない可能性があります。上記で作成されたコードの実装はすべて、エラーが発生しやすいものです。動作することもあれば、WebExpectionエラーメッセージが表示されることもあります。

より良い実装:

        try{
            using (var response = 
              WebRequest.Create("http://www.google.com").GetResponse())
                //string todaysDates =  response.Headers["date"];
                return DateTime.ParseExact(response.Headers["date"],
                    "ddd, dd MMM yyyy HH:mm:ss 'GMT'",
                    CultureInfo.InvariantCulture.DateTimeFormat,
                    DateTimeStyles.AssumeUniversal);
        }
        catch (WebException)
        {
            return DateTime.Now; //In case something goes wrong. 
        }

結論:

Webアプリを正確な日付情報を提供するサービスに依存させることが重要です。ここで作成したコードの1つをアプリで使用しましたが、本当に混乱しています。

9
cerberus

同じアイデアのもう1つのバージョン:

_public static class InternetTime
{
    public static DateTimeOffset? GetCurrentTime()
    {
        using (var client = new HttpClient())
        {
            try
            {
                var result = client.GetAsync("https://google.com", 
                      HttpCompletionOption.ResponseHeadersRead).Result;
                return result.Headers.Date;
            }
            catch
            {
                return null;
            }
        }
    }
}
_

ここでは_HttpCompletionOption.ResponseHeadersRead_を使用して、HTTPヘッダーのみが必要なため、残りの応答の読み込みを防ぎます。

InternetTime.GetCurrentTime().Value.ToLocalTime()を使用して、現在のローカル時間を取得します。

5
dodbrian

重要な最初の利用可能なサーバーを確認してください http://tf.nist.gov/tf-cgi/servers.cgi

        public static DateTime GetServerTime()
        {
            var result = DateTime.Now;

            // Initialize the list of NIST time servers
            // http://tf.nist.gov/tf-cgi/servers.cgi
            string[] servers = new string[] {

                "time-c.nist.gov",
                "time-d.nist.gov",
                "nist1-macon.macon.ga.us",
                "wolfnisttime.com",
                "nist.netservicesgroup.com",
                "nisttime.carsoncity.k12.mi.us",
                "nist1-lnk.binary.net",
                "wwv.nist.gov",
                "time.nist.gov",
                "utcnist.colorado.edu",
                "utcnist2.colorado.edu",
                "nist-time-server.eoni.com",
                "nist-time-server.eoni.com"
            };
            Random rnd = new Random();
            foreach (string server in servers.OrderBy(x => rnd.NextDouble()).Take(9))
            {                
                try
                {
                    // Connect to the server (at port 13) and get the response. Timeout max 1second
                    string serverResponse = string.Empty;
                    var tcpClient = new TcpClient();                        
                        if (tcpClient.ConnectAsync(server, 13).Wait(1000))
                        {
                            using (var reader = new StreamReader(tcpClient.GetStream()))
                            {
                                serverResponse = reader.ReadToEnd();
                            }
                        }                        
                    // If a response was received
                    if (!string.IsNullOrEmpty(serverResponse))
                    {
                        // Split the response string ("55596 11-02-14 13:54:11 00 0 0 478.1 UTC(NIST) *")
                        string[] tokens = serverResponse.Split(' ');

                        // Check the number of tokens
                        if (tokens.Length >= 6)
                        {
                            // Check the health status
                            string health = tokens[5];
                            if (health == "0")
                            {
                                // Get date and time parts from the server response
                                string[] dateParts = tokens[1].Split('-');
                                string[] timeParts = tokens[2].Split(':');

                                // Create a DateTime instance
                                    DateTime utcDateTime = new DateTime(
                                    Convert.ToInt32(dateParts[0]) + 2000,
                                    Convert.ToInt32(dateParts[1]), Convert.ToInt32(dateParts[2]),
                                    Convert.ToInt32(timeParts[0]), Convert.ToInt32(timeParts[1]),
                                    Convert.ToInt32(timeParts[2]));

                                // Convert received (UTC) DateTime value to the local timezone
                                result = utcDateTime.ToLocalTime();

                                return result;
                                // Response successfully received; exit the loop

                            }
                        }

                    }

                }
                catch
                {
                    // Ignore exception and try the next server
                }

            }
            return result;
        }
2
Xtian11