Event Times

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • gus
    Senior Member
    • Jan 2009
    • 134

    #1

    Event Times

    I've just noticed that, when calling listMarketCatalogue, to get, for example Horse Races, all of the times returned, e.g marketStartTime, and, if requested, suspendTime, marketTime etc are returned as GMT.

    For example with a call to listMarketCatalogue with the params:

    {"sort":"FIRST_TO_START","marketProjection":["MARKET_START_TIME","RUNNER_DESCRIPTION"],"maxResults":15,"filter":{"eventI
    ds":["27021640"]}}

    The data returned for the 14:15 Race at Brighton this afternoon


    [{"marketId":"1.109730208","marketName":"6f Mdn Stks","marketStartTime":"2013-06-10T13:15:00.000Z","runners":[{"selectio
    nId":7259777,"sortPriority":1,"handicap":0.0,"runn erName":"Stepping Out"},{"selectionId":7267834,"sortPriority":2,"han di
    cap":0.0,"runnerName":"Senorita Guest"},{"selectionId":7238086,"sortPriority":3,"h andicap":0.0,"runnerName":"Al Baz"},{"
    selectionId":7336344,"sortPriority":4,"handicap":0 .0,"runnerName":"G Man"}]}]

    whereas in the old API, at this time of year, I would get the times returned in BST, presumably based on my Account Settings?

    is there, or will there be in the production version, any way of getting location-specific times, or should we always expect to have to adjust the times in our clients.

    Another (related) point, I did wonder whether setting the locale param would return locale-specific times. I tried {"locale":"GB"} and {"locale":"UK"}, but both caused exceptions. Is there a list of acceptable locales somewhere?
  • AlgoTrader
    Junior Member
    • Mar 2012
    • 243

    #2
    What's the problem to convert time into the local timezone? That's very easy in most of languages. For example, JavaScript in browser I write this message from:

    Code:
    var d = new Date('2013-06-10T13:15:00.000Z');
    undefined
    
    d.toString()
    "Mon Jun 10 2013 17:15:00 GMT+0400 (Moscow time)"
    Betfair Bots Made Easy

    Comment

    • gus
      Senior Member
      • Jan 2009
      • 134

      #3
      It's not a problem. I just want to know whether it will be necessary, or whether it will be adjusted automatically at the Server (on the basis of the User's' account details) in the Production version, and, since I'll be producing clients that may be used anywhere, whether it will be necessary for the clients to check the Users' locations.

      Comment

      • Fred77
        Junior Member
        • Jan 2009
        • 37

        #4
        Unless I'm mistaken, the old API has always returned GMT no matter what time of year it is or what settings you have in your account, and it is the responsibility of your library/application to convert to local time if desired.

        Comment

        • BetfairDeveloperProgram
          Administrator
          • Oct 2008
          • 679

          #5
          Another (related) point, I did wonder whether setting the locale param would return locale-specific times. I tried {"locale":"GB"} and {"locale":"UK"}, but both caused exceptions. Is there a list of acceptable locales somewhere?
          Hi Gus,

          The locale, refers to the returned language. The locale specification is the same as API 6.0 i.e. ISO 639-1

          API-NG returns all times in GMT.

          Thanks

          Neil

          Comment

          • AlgoTrader
            Junior Member
            • Mar 2012
            • 243

            #6
            The old SOAP API return dates in inconsistent manner. Sometimes they are returned as timestamps and sometimes as XML dates.

            The new API is consistent in what dates are and that is good. The timestamps cannot be inspected visually, while the ISO date is a very good compromise between human readability and machine friendly format.

            It is up to software (and user) to choose how dates are represented. Personally, I like the GMT but most of users seem to like the local timezone format.
            Betfair Bots Made Easy

            Comment

            • gus
              Senior Member
              • Jan 2009
              • 134

              #7
              Originally posted by Fred77 View Post
              Unless I'm mistaken, the old API has always returned GMT no matter what time of year it is or what settings you have in your account, and it is the responsibility of your library/application to convert to local time if desired.
              actually Fred77, i think you'll find that, in the old API

              timeStamp = marketSummary.getStartTime();

              returned the time-adjusted (GMT or BST, as appropriate for the time of year) start time of Horse and Greyhound Races, which was quite handy for display purposes.

              i don't really care what times are returned by, e.g listMarketCatalogue, so long as they are consistent.

              Neil has explained that they will always be GMT, so that's fine

              but my main concern now is with scheduling events, e.g. starting to monitor the prices of an event 10 seconds before its scheduled off-time.

              currently, using the old API, i can do that by comparing the client computer's time with the Betfair server time and always adjusting for the difference, but, with the new API, i don't actually see any way of establishing what is the BF server time.

              Comment

              • Fred77
                Junior Member
                • Jan 2009
                • 37

                #8
                I'll agree to disagree gus, or rather, I'll agree that it must be inconsistent, as API6 GetEvents MarketSummary startTime is currently returned as GMT for me and my account is set to London/Europe.

                I have always got around the issue of GMT/BST times by converting all received times/dates to unix timestamps. Unix timestamps are always GMT.

                For every application cycle I'll compare current unix time with the stored timestamps to see which markets I should be interacting with.

                e.g. if (current_unix_time > stored_stamp-10) then begin strategy.

                If I want to display the date/time then I'll use a function that returns a textual representation of a unix stamp based on the local machine's time zone.

                Comment

                • gus
                  Senior Member
                  • Jan 2009
                  • 134

                  #9
                  well, here's the (unmodified) timestamp for today's 15.50 race at Fontwell (returned by marketSummary.getStartTime()):

                  java.util.GregorianCalendar[time=1370962200000,areFieldsSet=true,areAllFieldsS et=true,lenient=true,zone=sun.util.calenda
                  r.ZoneInfo[id="Europe/London",offset=0,dstSavings=3600000,useDaylight=tr ue,transitions=242,lastRule=java.util.SimpleTime
                  Zone[id=Europe/London,offset=0,dstSavings=3600000,useDaylight=tru e,startYear=0,startMode=2,startMonth=2,startDay=-1,star
                  tDayOfWeek=1,startTime=3600000,startTimeMode=2,end Mode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode
                  =2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,Y EAR=2013,MONTH=5,WEEK_OF_YEAR=24,WEEK_OF_MONTH=2,D AY_OF_MONTH=11,D
                  AY_OF_YEAR=162,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH= 2,AM_PM=1,HOUR=3,HOUR_OF_DAY=15,MINUTE=50,SECOND=0,MILLISECOND=0,ZONE_
                  OFFSET=0,DST_OFFSET=3600000]

                  Anyway, onward and upward.

                  I've put a routine into my new API app to detect GMT / BST from the startTime's date and then adjust the Display accordingly.

                  But I'm still a bit puzzled as to how to obtain the API server's time via the new API (so that I can offset the User's time by an appropriate amount of time for scheduling purposes).

                  Suggestions welcome!

                  Comment

                  • Fred77
                    Junior Member
                    • Jan 2009
                    • 37

                    #10
                    Originally posted by gus View Post
                    well, here's the (unmodified) timestamp for today's 15.50 race at Fontwell (returned by marketSummary.getStartTime()):
                    That has been modified from UTC/GMT to your machine's time zone by java.


                    Every JSON (HTTP) request you make will have a Date field in the HTTP response headers which you could sample and use to help sync if local machine time is unreliable.

                    Comment

                    • gus
                      Senior Member
                      • Jan 2009
                      • 134

                      #11
                      OK, got that.

                      It hadn't occurred to me to look at the Response Headers. I have done now, so now I can get the Response Time for synchronizing. Thanks.

                      As for the old API, it was just a case of "It works, (which it does) so leave it alone", I'm afraid.

                      Comment

                      • Mark Smeets
                        Junior Member
                        • Aug 2013
                        • 4

                        #12
                        in java?

                        Can anyone help me out with how to compare a marketTime (from the new api) with the current time, in java?

                        In the old api I got a Calendar object for startTime, and from there it was kind of straightforward to compare Calendar.getInstance() with startTime.

                        With the json stuff I get a Date object. I'm utterly clueless how to compare this to my local time (I'm in the Europe/Amsterdam timezone).

                        Can anybody help?

                        thanks,

                        Mark.

                        Comment

                        • gus
                          Senior Member
                          • Jan 2009
                          • 134

                          #13
                          Don't know whether my way of doing this is helpful, but it works for me:

                          First thing, I want to know (at any time), the time difference (in milliseconds) between the time on my computer and the time on BF's server, so in my Authentication class I compare those times when I log-in and whenever I call keepAlive (every 15 minutes). If you already have your own login etc routines, the important bit in this context is in "makeCall", where we get "timeDifference":

                          Code:
                          package com.XXX.XXX;
                          
                          import java.net.*;
                          import java.io.*;
                          import javax.net.ssl.HttpsURLConnection;
                          import java.util.*;
                          import java.text.SimpleDateFormat;
                          
                          
                          public class Authentication
                          	{
                          		private static String target = "https://identitysso.betfair.com/api/";
                          		
                          		private static long timeDifference = 0;
                          		private static SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss",Locale.ENGLISH);
                          		
                          		
                          		public Authentication()
                          			{
                          				;
                          			}
                          			
                          		public static String login()
                          			{
                          				String token = "PROBLEM";
                          				
                          				String s = "";
                          				
                          				try
                          					{
                          						s = "&username=" + URLEncoder.encode(Credentials.getUsername(), "UTF-8");
                          						s+= "&password=" + URLEncoder.encode(Credentials.getPassword(), "UTF-8");
                          						s+= "&login=" + URLEncoder.encode("true", "UTF-8");
                          						s+= "&redirectMethod=" + URLEncoder.encode("POST", "UTF-8");
                          						s+= "&product=" + URLEncoder.encode("home.betfair.int", "UTF-8");
                          						s+= "&url=" + URLEncoder.encode("https://www.betfair.com/", "UTF-8");
                          					}
                          				catch(Exception ex)
                          					{
                          						ex.printStackTrace();
                          						return token;
                          					} 
                          				
                          				if(!s.equals(""))
                          					token = makeCall("login", s);
                          				
                          				return token;
                          			}
                          			
                          		public static String keepAlive()
                          			{
                          				String token = "PROBLEM";
                          				String s = "";
                          				
                          				try
                          					{
                          						s = "&" + "product=" + URLEncoder.encode(JSONQuery.getAppKey(), "UTF-8");
                          						s+= "&url=" + URLEncoder.encode("https://www.betfair.com/", "UTF-8");
                          					}
                          					
                          				catch(Exception ex)
                          					{
                          						ex.printStackTrace();
                          						return token;
                          					} 
                          					
                          				if(!s.equals(""))
                          					token = makeCall("keepAlive", s);
                          				
                          				return token;
                          			}
                          			
                          		public static String logout()
                          			{
                          				String token = "PROBLEM";
                          				String s = "";
                          				
                          				try
                          					{
                          						s = "&" + "product=" + URLEncoder.encode(JSONQuery.getAppKey(), "UTF-8");
                          						s+= "&url=" + URLEncoder.encode("https://www.betfair.com/", "UTF-8");
                          					}
                          					
                          				catch(Exception ex)
                          					{
                          						ex.printStackTrace();
                          						return token;
                          					} 
                          					
                          				if(!s.equals(""))
                          					token = makeCall("logout", s);
                          				
                          				return token;
                          			}
                          			
                          		private static String makeCall(String mission, String query)
                          			{
                          				URL url = null;
                          				HttpsURLConnection conn = null;
                          				DataOutputStream outStream = null;
                          				String outString = "PROBLEM";
                          				
                          				String targetString = target + mission;
                          				
                          				try
                          					{
                          						url = new URL(targetString);
                          						conn = (HttpsURLConnection)url.openConnection();
                          						
                          						conn.setRequestMethod("POST");
                          						conn.setDoOutput(true);
                          						conn.setDoInput(true);
                          						conn.setFollowRedirects( true );
                          						
                          						if(conn != null)
                          							{
                          								outStream = new DataOutputStream(conn.getOutputStream());
                          						
                          								outStream.writeBytes(query);
                          								outStream.flush();
                          								outStream.close();
                          								conn.disconnect();
                          								
                          								int responseCode = conn.getResponseCode();
                          								
                          								String serverString = conn.getHeaderField("Date");
                          								Date d = null;	
                          				
                          								try
                          									{
                          										d = format.parse(serverString);
                          									}
                          								catch(Exception ex){System.out.println(ex.getMessage());}
                          								
                          								if(d != null)
                          									{
                          										long serverTime = d.getTime();
                          										long localTime = System.currentTimeMillis();
                          								
                          										timeDifference = serverTime - localTime;
                          									}
                          								
                          								
                          								if(mission.equals("login"))
                          									{
                          										if(responseCode == 200)
                          											{
                          												String headerName = null;
                          												
                          												for (int i = 1; (headerName = conn.getHeaderFieldKey(i))!=null; i++) 
                          													{
                          														if (headerName.equals("Set-Cookie")) 
                          															{                  
                          																String cookie = conn.getHeaderField(i);
                          														
                          																if(cookie.indexOf("ssoid") > -1)
                          																	outString = cookie.substring(cookie.indexOf("=") + 1, cookie.indexOf(";"));
                          															}
                          															
                          													}
                          											}
                          									}
                          						 	
                          								else if(responseCode == 200)
                          									outString = "" + responseCode;
                          							}//if(conn != null)
                          					}
                          					
                          				catch(Exception ex)
                          					{
                          						ex.printStackTrace();
                          						return outString;
                          					}
                          					
                          				return outString;
                          			}
                          			
                          		public static long getTimeDifference()
                          			{
                          				return timeDifference;
                          			}
                          	}
                          So now, from anywhere in my programme I can get the time-difference by calling Authentication.getTimeDifference(), and I can set the current Betfair time as:

                          long bfTime = System.currentTimeMillis() + Authentication.getTimeDifference();

                          Next problem is how to get a meaningful time out of e.g. the marketStartTime contained in a MarketCatelogue object.

                          I start by getting the marketStartTime as a String from the MarketCatalogue:

                          if(marketCatalogue.containsKey("marketStartTime"))
                          String marketStartTime = (String)marketCatalogue.get("marketStartTime");
                          but I want milliseconds, not a String, so first I get a Timestamp by passing the String to a utility method that I have in my Utilities class which parses the String into a java.sql.Timestamp :

                          Code:
                          public static Timestamp jsonToTimestamp(String s)
                          	{
                          		Timestamp out = null;
                          
                          		if(s != null && !s.equals(""))
                          			{
                          				s = s.substring(0, s.indexOf("."));
                          				s = s.replace('T', ' ');
                          
                          				out = Timestamp.valueOf(s);
                          			}
                          
                          		return out;
                          	}
                          so now I've got a Timestamp, and I can convert it to milliseconds with ts.getTime();

                          so, at last I now have the marketStartTime in millis and the Betfair Time in millis and I can compare them:

                          if(ts.getTime() >= bfTime)
                          //do something;
                          else
                          //forget/it. its too late;
                          so put together in one method (and assuming you already have a MarketCatalogue object) , it might look like:


                          Code:
                          long bfTime = System.currentTimeMillis() + Authentication.getTimeDifference();
                          Timestamp ts = null;
                          String mst = "";
                          
                          if(marketCatalogue.containsKey("marketStartTime"))
                          	mst = (String)marketCatalogue.get("marketStartTime");
                          
                          if(!mst.equals(""))
                          	{
                          		mst = mst.substring(0, mst.indexOf("."));
                          		mst = mst.replace('T', ' ');
                          
                          		ts = Timestamp.valueOf(mst);
                          	}
                          
                          if(ts != null)
                          	{
                          		if(ts.getTime() >= bfTime)
                          			System.out.println("Do Something");
                          		else
                          			System.out.println("Forget it. Is too Late!");
                          
                          	}

                          Comment

                          • Mark Smeets
                            Junior Member
                            • Aug 2013
                            • 4

                            #14
                            thanks

                            Thanks, really helpful!

                            The problem was that the Date object returned by gson was not in gmt but local time. Your solution would have worked, although I fixed it by creating a DateTypeAdapter and register an instance of it on the gsonbuilder.

                            Mark.

                            Comment

                            • gus
                              Senior Member
                              • Jan 2009
                              • 134

                              #15
                              Good, glad it's sorted.

                              For no particular reason, apart from personal preference, I'm trying to make my API-NG apps as dependency-free as possible, just Java and JSON.simple.

                              So no Axis, and therefore no DateTypeAdapter, hence the string-parsing.

                              I'm probably storing up trouble for myself, but I just like knowing exactly what the hell is going on in there so that I can (usually) spot where I've screwed up!

                              Comment

                              Working...
                              X