Android Question Convert UTC to ticks and vice versa

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
I am retrieving a time-stamp that can come in one of three flavors:
"2014-01-01T03:08:04+0000" or "2014-01-02T17:06:18.866Z" or "Sun Jan 05 22:54:05 +0000 2014". When I dealt with these in .NET I used the built-in properties of the Date object to convert them to/from local time:

B4X:
    Public Function UTCToLocalTime(ByVal UTCTime As String) As Date
        Dim strDT As String = UTCTime
        Dim datDT As DateTime = DateTime.Parse(strDT, System.Globalization.CultureInfo.InvariantCulture)
        datDT = datDT.ToLocalTime
        Return datDT
    End Function

    Public Function LocalTimeToUTC(ByVal LocalTime As Date) As String
        Dim datDT As DateTime

        datDT = LocalTime.ToUniversalTime
        Dim strDT As String = datDT.ToString(System.Globalization.CultureInfo.InvariantCulture)
        Return strDT
    End Function
I have not been able to find something equivalent in your DateTime library, how would I go about translating these functions to B4A?

Thanks in advance,
- Richard
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
As workaround you could use regexp to replace the Z with an UTC timezoneinformation. hopefully it helps.
If not; sorry for my idea
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
I always appreciate all suggestions, re-parsing the string into another UTC format was the least of my problems ;)

Assuming I can just replace the "Z" with "+0000", I was wondering what built-in function or library I could use to take a given UTC string and convert to local time on the device, and vice-versa -- take the current time on the device and change it into a UTC string?

I've tried the brute-force method, but even that method is not returning the correct value:

B4X:
Sub UTCToLocal(UTCTimeString As String) As Long
    ' Sun Jan 05 22:54:05 +0000 2014
    Dim RegExPat1 As String  = "((?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday|Tues|Thur|Thurs|Sun|Mon|Tue|Wed|Thu|Fri|Sat))" & "(\s+)" & _
                            "((?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Sept|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?))" & "(\s+)" & _
                                "(\d+)(\s+)(\d+)(.)(\d+)(.)(\d+)(\s+)([-+]\d+)(\s+)((?:(?:[1]{1}\d{1}\d{1}\d{1})|(?:[2]{1}\d{3})))(?![\d])"      

    ' 2014-01-01T03:08:04+0000                      
    Dim RegExPat2 As String  = "((?:2|1)\d{3}(?:-|\/)(?:(?:0[1-9])|(?:1[0-2]))(?:-|\/)(?:(?:0[1-9])|(?:[1-2][0-9])|(?:3[0-1]))(?:T|\s)(?:(?:[0-1][0-9])|(?:2[0-3])):(?:[0-5][0-9]):(?:[0-5][0-9]))"    & _ 'Time Stamp 1'
                                "([-+]\d+)"      
  
    ' 2014-01-02T17:06:18.866Z
    Dim RegExPat3 As String = "((?:2|1)\d{3}(?:-|\/)(?:(?:0[1-9])|(?:1[0-2]))(?:-|\/)(?:(?:0[1-9])|(?:[1-2][0-9])|(?:3[0-1]))(?:T|\s)(?:(?:[0-1][0-9])|(?:2[0-3])):(?:[0-5][0-9]):(?:[0-5][0-9]))" & _
                                "(\.)(\d)(\d)(\d)(Z)"
  
    Dim psDateFmt As String
    Dim plTicks As Long = 0
  
    If Regex.IsMatch2(RegExPat1, Regex.CASE_INSENSITIVE, UTCTimeString) = True Then
        psDateFmt = "EEE MMM dd HH:mm:ss Z yyyy"
    Else
        If Regex.IsMatch2(RegExPat2, Regex.CASE_INSENSITIVE, UTCTimeString) = True Then
            psDateFmt = "yyyy-MM-dd'T'HH:mm:ssZ"
        Else
            If Regex.IsMatch2(RegExPat3, Regex.CASE_INSENSITIVE, UTCTimeString) = True Then
              psDateFmt = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
            Else
                Return -1
            End If
        End If
    End If

    Dim psCurrFmt As String
    Dim piCurrOff As Int
  
    psCurrFmt = DateTime.DateFormat
    piCurrOff = DateTime.TimeZoneOffset
  
    DateTime.DateFormat = psDateFmt
    DateTime.SetTimeZone(0)
    plTicks = DateTime.DateParse(UTCTimeString)
  
  
    DateTime.DateFormat = psCurrFmt
    DateTime.SetTimeZone(piCurrOff)
  
    Return plTicks
End Sub

Pass in "2014-01-01T03:08:04+0000" and it returns 7/31/2014 19:00:04, so clearly I am failing to grasp some basic property of these methods.
 
Last edited:
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi Jeffrey,

have a look at this thread.
I'm not sure to have correctly understood your needs, but function SetDateAndTime2 should be able to convert a date/time local to the time zone entered as last parameter to the same date/time referring to UTC 0.
In that same code module there are functions to convert to/from Unix time.

Sorry if I missed the point.

Umberto
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
I tried my code I posted above and it is returning the correct value now... I blame lack of sleep ;)

Now, I am having a problem with the convert to UTC method:

B4X:
Sub LocalTimeToUTC(lTicksIn As Long) As String
    Dim psCurrFmt As String
    Dim piCurrOff As Int
    Dim psDate As String
  
    psCurrFmt = DateTime.DateFormat
    piCurrOff = DateTime.TimeZoneOffset
  
    DateTime.DateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
    DateTime.SetTimeZone(0)
    psDate = DateTime.Date(lTicksIn)
  
    DateTime.DateFormat = psCurrFmt
    DateTime.SetTimeZone(piCurrOff)
  
    Return psDate
End Sub

My FromUTC, passing in the same string as above (""2014-01-01T03:08:04+0000") returns a number ticks equivalent to my Pacific-Standard-Time device (12/31/2013 19:08:04) but when I pass that same number of ticks into my ToUTC function, it returns "2014-01-01T03:08:04-0800" instead of "2014-01-01T03:08:04+0000" as I would expect.

What did I mess up, and is there an easier set of built-in methods to perform this function?
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
You can use this code:
B4X:
Sub Activity_Create(FirstTime As Boolean)
   Log(DateUtils.TicksToString(ParseUTCstring("2014-01-01T03:08:04+0000")))
   Log(DateUtils.TicksToString(ParseUTCstring("2014-01-02T17:06:18.866Z")))
   Log(DateUtils.TicksToString(ParseUTCstring("Sun Jan 05 22:54:05 +0000 2014")))
End Sub

Sub ParseUTCstring(utc As String) As Long
   Dim df As String = DateTime.DateFormat
   Dim res As Long
   If utc.CharAt(10) = "T" Then
     'convert the second format to the first one.
     If utc.CharAt(19) = "." Then utc = utc.SubString2(0, 19) & "+0000"
     DateTime.DateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
   Else
     DateTime.DateFormat = "EEE MMM dd HH:mm:ss Z yyyy"
   End If
   Try
     res = DateTime.DateParse(utc)
   Catch
     res = 0
     LogColor("Error parsing: " & utc, Colors.Red)
   End Try
   DateTime.DateFormat = df
   Return res
End Sub
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
Erel,

Thanks for that routine, it is a bit less heavy-handed than mine. My subsequent question remains: How can I convert a local tick value to a "+0000" UTC string value. The routine I posted in thread number 7 above seems to me to be returning an incorrect timezone offset or am I misunderstanding how the SetTimeZone method works?
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
Using your routine, I pass in "2014-01-01T03:08:04+0000" and it returns a long tick value which corresponds to a date/time value localized to the device:
12/31/2013 19:08:04 (1388545684000 ticks)
I then store this tick value in a database. At some future point, I wish to take this long value and restore it to the original UTC string I passed in, as I understand it this code should do that:

B4X:
DateTime.DateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
DateTime.SetTimeZone(0)
psDate = DateTime.Date(1388545684000)
The string that is returned is "2014-01-01T03:08:04-0800" which is not correct, the "-0800" should be "+0000" should it not?
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
:oops: I tried your routine, it worked fine, so I tried my routine and it worked fine too. I'm not sure what I was initially doing to produce the incorrect result but I'll just write it off to my incompetence for now.

Thanks for all your time and attention!

- Richard
 
Upvote 0

jcredk

Member
Licensed User
Longtime User
Hi all,
My date strings are comming with the format as in the following sample: "Wed, 05 Feb 2014 06:55:39 GMT".
Unfortunatly from a source system I am not responsible of, or that I can't influence for change :(

Would you be kind to tell me how to adapt the upper "parse" function "format string" to be able to parse this one also ?

Thanks

Jo
 
Upvote 0
Top