Sunday 22 February 2015

WatchMaker - adding internet time

I was reading through the Feature Requests for WatchMaker and stumbled across this one for adding Internet time (@.beats).  Internet time was dreamt up by the Swatch corporation as part of their marketing campaign for their line of "Beat" watches in 1998.  Instead of hours and minutes, the day is divided up into 1000 parts called ".beats".  The idea was to have a time that was consistent around the word, so there are no timezones and no daylight savings.  0 beats starts at midnight in UTC+1.

I was interested in seeing what I could come up with, so I set about seeing what WatchMaker could do.

So I did some research, and according to Wikipedia, the calculation for converting from UTC+1 to beats is...
(UTC+1seconds + (UTC+1minutes * 60) + (UTC+1hours * 3600)) / 86.4

At first I thought that if I set the time settings in WatchMaker so that the Extra Time Zone 1 was UTC+1 (France)) then use the rotation values to calculate the beats.  If you divide these by 360 (the total rotational value) then you can calculate the percentage and from this work out the hours and minutes.  This worked ok, but the accuracy wasn't great.  It also meant that the setting would need to be changed during daylight savings time, which would be annoying.




So I decided to come at it more directly, going back to the original calculation.  So I converted the calculation into tags...
({ds} + ({dm} * 60) + ({dh23} * 3600)) / 86.4

Whilst many places will show the decimal part of the beats value, the value is supposed to be integer.  WatchMaker uses the LUA syntax, which includes some maths functions we can use...
math.floor(({ds} + ({dm} * 60) + ({dh23} * 3600)) / 86.4)

I'm in the UK, so currently in the "GMT" timezone, which means I need to add an hour onto the hours (GMT is UTC).  However, "BST" (British Summer Time which is UTC+1) is coming up in a few months, so I want to account for this as well.  This can be done using LUA conditionality (as discussed in a previous blog post)...
math.floor(({ds} + ({dm} * 60) + (({dh23} + ("{dz}"=="GMT" and 1 or 0)) * 3600)) / 86.4)

This checks for the "GMT" timezone (using the {dz} tag) and adds 1 if it is, otherwise it doesn't.  Obviously this will only work in the UK, but it would take a lot of conditional statements to account for the ~50 timezones (including daylight savings, etc).  So this would have to do for now.

The trouble with adding the extra hour is that it goes up to 1041 instead of 999, but as it should loop back to 0 instead of going on to 1000, then easiest way to fix this is to take the last 3 characters of the string.  Luckily LUA also gives us some string functions to use...
string.sub(math.floor(({ds} + ({dm} * 60) + (({dh23} + ("{dz}"=="GMT" and 1 or 0)) * 3600)) / 86.4),-3)

The "string.sub" method is used to create a substring, and the -3 means to take the last 3 characters.  

Personally I prefer to always display 3 characters, so "000" instead of "0".  The easiest way to do this, given the string manipulation that we're already doing, is to always add 1000 to the value.  This means that the value will go from 1041 to 2041, but as we're always taking the last three characters, the first character is not needed...
string.sub((math.floor(({ds} + ({dm} * 60) + (({dh23} + ("{dz}"=="GMT" and 1 or 0)) * 3600)) / 86.4) + 1000),-3)

I've not managed to fully test this, but I've been comparing it to other sources and it certainly seems to work correctly.  

I wanted to update this watch face to FaceRepo, but unfortunately I got an error message saying that there were copyright issues, so I'm guessing "Swatch" is a dirty word!  Here's what it looks like though...




I added the real time as well, because how many people really use internet time?  It was an interesting challenge though.  Hopefully the WatchMaker developer will be able to make more UTC time and timezone properties available, which will make this kind of calculation easier in future, across any timezone.


No comments:

Post a Comment