Search Unity

Server-Internet Unix time for unity

Discussion in 'Scripting' started by skdev3, Feb 27, 2018.

  1. skdev3

    skdev3

    Joined:
    Jul 15, 2015
    Posts:
    64
    Hi Unity community
    How good is this solution for getting server time?

    Code (csharp):
    1.  
    2.  
    3. using System.Collections;
    4. using UnityEngine;
    5. using System;
    6. using UnityEngine.Networking;
    7. using System.Collections.Generic;
    8. using System.Text;
    9. using System.Globalization;
    10.  
    11.  
    12. public class UnixTimeModelData
    13. {
    14.     public System.Action<double> result = null;
    15.     public UnixTimeModelData(System.Action<double> _result) { result = _result; }
    16. }
    17.  
    18. public class GetServerUnixTime : MonoBehaviour
    19. {
    20.     public double Unixtime = 0;
    21.     void Start()
    22.     {
    23.         Get(new UnixTimeModel(doubleUnixtime =>
    24.         {
    25.             Unixtime = (double)doubleUnixtime;
    26.             Debug.Log("GetUnixTime:" + Unixtime.ToString());
    27.         }));
    28.     }
    29.  
    30.     public void Get(UnixTimeModel actiontime)
    31.     {
    32.         string url = "http://www.google.com/";
    33.         StartCoroutine(GetTime(System.Uri.EscapeUriString(url), actiontime.result));
    34.     }
    35.  
    36.     IEnumerator GetTime(string url, Action<double> _result)
    37.     {
    38.         UnityWebRequest myHttpWebRequest = UnityWebRequest.Get(url);
    39.         yield return myHttpWebRequest.Send();
    40.  
    41.         string netTime = myHttpWebRequest.GetResponseHeader("date");
    42.         DateTime time = DateTime.ParseExact(netTime,
    43.                        "ddd, dd MMM yyyy HH:mm:ss 'GMT'",
    44.                        CultureInfo.InvariantCulture.DateTimeFormat,
    45.                        DateTimeStyles.AssumeUniversal);
    46.         double unixtime = Math.Truncate((time.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
    47.         _result(unixtime);
    48.     }
    49.  
    50. }
    51.  
    52.  
     
  2. gegebel

    gegebel

    Joined:
    Jan 29, 2014
    Posts:
    469
    why not use a simple DateTime.now ?
    It will return the actual system time.

    or use DateTime.UtcNow for universal time and convert later to TimeZone ?
     
  3. jschieck

    jschieck

    Joined:
    Nov 10, 2010
    Posts:
    429
    This allows the user to just change the time to whatever they want on the device.

    I don't see why this wouldn't work, assuming Google never goes down :p
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Sure, but why the 'UnitTimeModelData' class? It's all a bit over kill, and would generate a bunch of garbage for the GC to clean up. Which is considered an issue in Unity since it's garbage collector is sort of naive. Why not just pass in the 'Action' directly rather than having to wrap it in this model class (you come from some MVC I presume, ASP.Net MVC 5 probably?).

    Also, what is the point of the 'Unixtime' field? It's set only once during Start, and never again. If this is to store the time it started at... the name is a bit peculiar.

    Also, why pass the url as a parameter like that? Why not just make it a const and use it directly in the coroutine? You could also call escape on it just once instead of every time you call 'Get'. Heck, you don't even have to escape the uri since it's already clean.

    Lastly, why is it in its own MonoBehaviour? Now you gotta get a hold of a MonoBehaviour to check the time. How about abstract this into its own class?

    It could be something like this following the common design of yield instructions in unity:
    Code (csharp):
    1.  
    2. //implement IEnumerator so it can be used as a yield instruction
    3. public class NetworkTime : IEnumerator
    4. {
    5.  
    6.     private const string SERVER = "http://www.google.com/";
    7.  
    8.     private System.DateTime? _time;
    9.     private UnityWebRequestAsyncOperation _request;
    10.  
    11.     public NetworkTime()
    12.     {
    13.         this.Reset();
    14.     }
    15.  
    16.     #region Properties
    17.  
    18.     public System.DateTime Time
    19.     {
    20.         get
    21.         {
    22.             if(_time == null)
    23.             {
    24.                 if(this.IsDone)
    25.                 {
    26.                     string netTime = _request.webRequest.GetResponseHeader("date");
    27.                     var time = System.DateTime.ParseExact(netTime,
    28.                                    "ddd, dd MMM yyyy HH:mm:ss 'GMT'",
    29.                                    CultureInfo.InvariantCulture.DateTimeFormat,
    30.                                    DateTimeStyles.AssumeUniversal).ToUniversalTime();
    31.                     _time = time;
    32.                     return time;
    33.                 }
    34.                 else
    35.                 {
    36.                     return System.DateTime.UtcNow;
    37.                 }
    38.             }
    39.             return _time.Value;
    40.         }
    41.     }
    42.  
    43.     public bool IsDone
    44.     {
    45.         get { return _request.isDone; }
    46.     }
    47.  
    48.     #endregion
    49.  
    50.     #region IEnumerator Interface
    51.  
    52.     object IEnumerator.Current
    53.     {
    54.         get { return _request; }
    55.     }
    56.  
    57.     bool IEnumerator.MoveNext()
    58.     {
    59.         return !this.IsDone;
    60.     }
    61.  
    62.     //Reset the NetworkTime to poll again
    63.     public void Reset()
    64.     {
    65.         _time = null;
    66.         _request = UnityWebRequest.Get(SERVER).SendWebRequest();
    67.     }
    68.  
    69.     #endregion
    70.  
    71. }
    72.  
    Used like so in a coroutine:

    Code (csharp):
    1.  
    2. var time = new NetworkTime();
    3. yield return time;
    4. Debug.Log(time.Time); //if you want to convert to your seconds since 1970, you can do so here
    5.  
    Of course... if I was doing this, I'd probably use an NTP server:
    https://en.wikipedia.org/wiki/Network_Time_Protocol

    Probably google's ntp server:
    time.google.com
     
    Last edited: Feb 28, 2018