Sugar TimeSpan vs. Timespan

Hi,

I’m trying to write a simple profiler to measure how long operations take and the simplest way that I can see of doing this with Sugar is something like:

let startTicks = DateTime.Now.Ticks ...execute operation... let endTicks = DateTime.Now.Ticks let msTaken = endTime.Subtract(startTime).Milliseconds

However when I try to use DateTime.Now.Ticks I’m shown a compile time error that Timespan doesn’t exist, unless I’m mistaken it should be TimeSpan?

I’d make the change myself to test it but my Oxygene licence has expired, I do see a number of occurrences of Timespan in the DateTime.pas file.

Cheers,

Sevan

Ah, I see now that I can actually do:

let startTime = DateTime.Now ... execute operations... let endTime = DateTime.Now let elapsed = endTime - startTime

This produces the same compile time error though

Cheers,

Sevan

What platform does this fail on?

I’ve fixed the case mismatches in Sugar itself, but it’s definitely a compiler bug that these bubble up into your Swift code, so that’s something we’ll need to address separately. Mean time, if toys rebuild latest Sugar from github (no Oxygene license needed to do that), the error should go away.

Thanks, logged as bugs://74243: Bad casing in Sugar bubbles up as error when used from Swift

Thanks, I’ll try out the new code.

I was compiling for iOS when I saw this.

Cheers,

Sevan

Out of curiosity, why was the error only triggered when I tried to use DateTime.Subtract() but not when I used other DateTime functionality?

Is it a feature of some part of the system that only library code which is used will be resolved to an actual class or protocol?

Cheers,

Sevan

I can’t say. It seems to be a bug in the compiler with how inlined code written in Oxygene (which is case insensitive) gets processed when used from Swift (which is case sensitive).

I’m getting a similar compiler error here:

if response.Success {
				var jsonObject:Sugar.Json.JsonObject = response.Content.RootObject;
				
				let rndIndex=(Sugar.Random()).NextInt();
				let key="USER_"+Sugar.Convert.ToString(rndIndex);
				let now = DateTime.Now
				
				var cacheObject:CacheObject = CacheObject(key:key,
					value:jsonObject.ToString(),
					timestamp: Convert.ToString( now.Ticks ) );
					cacheObject.Load( jsonObject.ToString() );
				
				self.logger.debug( "CACHE OBJECT "  + cacheObject.timestamp );
				
				
				
				success( jsonObject.ToString() );
			}

The line now.Ticks causes a

/Volumes/MacHDD2/Developmemt/ParisiLabs/swift-promise-example/StaticLibrary/SharedProject/APIClient.swift(60,35): error E46: Unknown identifier "Timespan"

and I suppose reading this thread that is due to the underlining Timespan notation of TimeSpan in Sugar DateTime.pas - https://github.com/remobjects/sugar/blob/254aba8a77c3d719a3eec85e9441ac6275ad49fe/Sugar/DateTime.pas here:

property Ticks: Int64 read{$IFDEF COOPER}(mapped.TimeInMillis +mapped.TimeZone.getOffset(mapped.TimeInMillis)) * Timespan.TicksPerMillisecond + TicksSince1970{$ELSEIF ECHOES}mapped.Ticks{$ELSE}Int64((mapped.timeIntervalSince1970 + DateTimeHelpers.LocalTimezone.secondsFromGMTForDate(mapped)) * Timespan.TicksPerSecond) + TicksSince1970{$ENDIF};

Compiling Sugar.DateTime.pas after replacing all occurrences of Timespan with TimeSpan, (ignoring System.Timespan), seems to work:

01-26 15:06:02.539 26015-26053/? I/System.out: CACHE OBJECT 635894175625250000

where: the log was from Convert.ToString( now.Ticks )

Given that my aim was to take unix timestamp / milliseconds from 1970 i.e.

macbookproloreto:home admin$ date +%s
1453817557

and that is not (I’m using the wrong conversion), it compiles.

Hmm, are you saying i missed some instances? i through i fixed them all. Checking again.

yep exactly some typo occurrences :slightly_smiling:

btw regarding the unix epoch I came out with

let now = DateTime.Now
let unixMsec = (now.Ticks - DateTime.TicksSince1970 ) / TimeSpan.TicksPerSecond;

that prints out

01-26 16:10:41.287 27728-27755/? I/System.out: 1453824641

i.e.

macbookproloreto:swift-promise-example admin$ date -r1453824641
Mar 26 Gen 2016 17:10:41 CET

The issue here is that now it’s actually GMT+1 and so

macbookproloreto:swift-promise-example admin$ date +%s
1453821311
macbookproloreto:swift-promise-example admin$ date -r1453821311
Mar 26 Gen 2016 16:15:11 CET

Odd, i just checked and found none. all have the proper case now. Sure the have the latest revision checked out?

hmm, maybe you need to use DateTime.UtcNow? I’m not sure how this all is supposed to work, but we just pass the core system APIs thru. What platform are you on, Cocoa? Does the same give different results on .NET or Java?

Well, I’m using the latest develop branch + the (temporary) hotfix I did for the SQLite statement issue, latest commit was

commit bafb9540ad64dc3adca6f62fbd02db7379e8b17c
Merge: 6bdb587 a80d12c
Author: Carlo Kok <ck@remobjects.com>
Date:   Thu Jan 14 09:46:33 2016 +0100

    Merge branch 'develop' of github.com:remobjects/sugar into develop

Let me check the UtcNow (both Java and Cocoa).

@mh So, I’ve just checked, in both Android Java & Cocoa I get the GMT/CET instead of GMT+1 and so:

macbookproloreto:swift-promise-example admin$ date -r1453827185
Mar 26 Gen 2016 17:53:05 CET 

while I find no references to DateTime.UtcNow in COOPER or NOUGAT in the Sugar develop tree.
Is it in a different branch?

Hmm, looks like we dint expose this yet. this seems tricky, on Cocoa, NSDateTimes are always time-zone agnostic (ie NSDate.date is UTC, in essence), it’s during printing and conversion that it gets adjusted to a local timezone. By contrast, .NET exposes DateTime.Now (local) and DateTime.UtcNow (UTC) so apparently each time instance carries a timezone with it… this complicates things :(.

That said, no idea ion that is your issue, it sounds like its shouldn’t be, if you are on Cocoa. But i known very little about how UNIX epochs work, excalty.

I’m tempted to drop DateTime.Now from Sugar and only expose DateTime.UtcNow.

@mh Could be a solution!
In fact in my SDK to handle the UTC issue I’m doing like a specific NSDateFormatter like

         // UTC formatter posix locale
        NSTimeZone *utcTimeZone = [NSTimeZone timeZoneWithName:@"UTC"];
        utcDateFormatter = [[NSDateFormatter alloc] init];
        [utcDateFormatter setDateFormat: @"YMMdd"];
        [utcDateFormatter setTimeZone:utcTimeZone]; 

and then

/**
 * UTC Date to String
 */
-(NSString*)formatUTCDate:(NSDate*)date {
    NSString *stringDate = [utcDateFormatter stringFromDate:date];
    return stringDate;
}

so I can do like

[[MXMUtil sharedInstance] formatUTCDate:[NSDate date]]

Maybe having a generic formatter it would be possibile to do conversions like:

         // UTC ISO formatter
        utcISODateFormatter = [[NSDateFormatter alloc] init];
        [utcISODateFormatter setDateFormat:API_DATETIME_FORMAT_UTC_ISO];

Where:

#define API_DATETIME_FORMAT_UTC_ISO @"yyyy-MM-dd'T'HH:mm:ss'.'SSSZ'"

in order to have a helper to do

/**
 * UTC ISO Date to String
 */
-(NSString*)formatUTCISODate:(NSDate*)date {
    NSString *stringDate = [utcISODateFormatter stringFromDate:date];
    return stringDate;
}

something like that.

How does this work for you:

    class property Epoch: Int64 read {$IF COOPER}java.util.Calendar.Instance.getTimeInMillis(){$ELSEIF ECHOES}System.DateTime.Now.Subtract(new System.DateTime(1970, 1, 1, 0, 0, 0, 0,DateTimeKind.Utc)).Milliseconds{$ELSEIF NOUGAT}Int64(NSDate.date.timeIntervalSince1970*1000){$ENDIF};