Skip to content

Commit 41a0bc2

Browse files
author
Rhys Gray
committed
Initial
1 parent 91cd601 commit 41a0bc2

File tree

3 files changed

+194
-5
lines changed

3 files changed

+194
-5
lines changed

lib/client/clock-client.js

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
'use strict';
22

33
var browserSettings = require('./browser-settings');
4+
var moment = require('moment-timezone');
5+
var timeformat = require('./timeformat');
46
var client = {};
57
var latestProperties = {};
8+
var profileTimezone = null;
69

710
client.query = function query () {
811
var parts = (location.search || '?').substring(1).split('&');
@@ -35,6 +38,39 @@ client.query = function query () {
3538
});
3639
};
3740

41+
client.queryProfile = function queryProfile () {
42+
var parts = (location.search || '?').substring(1).split('&');
43+
var token = '';
44+
parts.forEach(function(val) {
45+
if (val.startsWith('token=')) {
46+
token = val.substring('token='.length);
47+
}
48+
});
49+
50+
var secret = localStorage.getItem('apisecrethash');
51+
var src = '/api/v1/profile.json';
52+
53+
if (secret) {
54+
var s = '?secret=' + secret;
55+
src += s;
56+
} else if (token) {
57+
var s2 = '?token=' + token;
58+
src += s2;
59+
}
60+
61+
$.ajax(src, {
62+
error: function gotError (err) {
63+
console.error('Error fetching profile:', err);
64+
}
65+
, success: function gotData (data) {
66+
if (data && data.length > 0 && data[0].store && data[0].store.Default && data[0].store.Default.timezone) {
67+
profileTimezone = data[0].store.Default.timezone;
68+
console.log('Profile timezone:', profileTimezone);
69+
}
70+
}
71+
});
72+
};
73+
3874
client.render = function render () {
3975

4076
if (!latestProperties.bgnow && !latestProperties.bgnow.sgvs) {
@@ -189,23 +225,72 @@ client.render = function render () {
189225

190226
function updateClock () {
191227
let timeDivisor = parseInt(client.settings.timeFormat ? client.settings.timeFormat : 12, 10);
192-
let today = new Date()
193-
, h = today.getHours() % timeDivisor;
228+
229+
// Get device time and offset using shared utilities
230+
let deviceTime = timeformat.getDeviceTime(profileTimezone, moment);
231+
let deviceOffsetSeconds = timeformat.getTimezoneOffsetSeconds(profileTimezone, moment);
232+
233+
// Fall back to browser time if no device timezone
234+
if (!deviceTime) {
235+
deviceTime = new Date();
236+
}
237+
238+
// Format device time
239+
let h = deviceTime.getHours() % timeDivisor;
194240
if (timeDivisor === 12) {
195241
h = (h === 0) ? 12 : h; // In the case of 00:xx, change to 12:xx for 12h time
196242
}
197243
if (timeDivisor === 24) {
198244
h = (h < 10) ? ("0" + h) : h; // Pad the hours with a 0 in 24h time
199245
}
200-
let m = today.getMinutes();
246+
let m = deviceTime.getMinutes();
201247
if (m < 10) m = "0" + m;
202-
$('.tm').html(h + ":" + m);
248+
249+
// Check if we need to show both times (different UTC offsets)
250+
let showBothTimes = timeformat.shouldShowBothTimes(deviceOffsetSeconds);
251+
252+
if (showBothTimes) {
253+
// Format browser local time
254+
let browserTime = new Date();
255+
let browserH = browserTime.getHours() % timeDivisor;
256+
if (timeDivisor === 12) {
257+
browserH = (browserH === 0) ? 12 : browserH;
258+
}
259+
if (timeDivisor === 24) {
260+
browserH = (browserH < 10) ? ("0" + browserH) : browserH;
261+
}
262+
let browserM = browserTime.getMinutes();
263+
if (browserM < 10) browserM = "0" + browserM;
264+
265+
// Display both times with separate spans for styling
266+
$('.tm').html(
267+
h + ":" + m + " <span class=\"device-label\">(Device)</span><br>" +
268+
"<span class=\"local-time\">" + browserH + ":" + browserM + " (Local)</span>"
269+
);
270+
271+
// Apply styles via CSS
272+
$('.tm .device-label').css({
273+
'font-size': '0.6em',
274+
'opacity': '0.7'
275+
});
276+
$('.tm .local-time').css({
277+
'font-size': '0.8em',
278+
'opacity': '0.6'
279+
});
280+
} else {
281+
// Display only device time (or browser time if no device data)
282+
$('.tm').html(h + ":" + m);
283+
}
203284
}
204285

205286
client.init = function init () {
206287

207288
console.log('Initializing clock');
208289
client.settings = browserSettings(client, window.serverSettings, $);
290+
291+
// Fetch profile timezone once on initialization
292+
client.queryProfile();
293+
209294
client.query();
210295
setInterval(client.query, 20 * 1000); // update every 20 seconds
211296

lib/client/index.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ var units = require('../units')();
1313
var levels = require('../levels');
1414
var times = require('../times');
1515
var receiveDData = require('./receiveddata');
16+
var timeformat = require('./timeformat');
1617

1718
var brushing = false;
1819

@@ -874,7 +875,40 @@ client.load = function load (serverSettings, callback) {
874875
return;
875876
}
876877
client.now = Date.now();
877-
$('#currentTime').text(formatTime(new Date(client.now), true)).css('text-decoration', '');
878+
879+
// Get device timezone from profile
880+
var deviceTimezone = client.profilefunctions && client.profilefunctions.getTimezone ? client.profilefunctions.getTimezone() : null;
881+
882+
// Get device time and offset using shared utilities
883+
var deviceTime = timeformat.getDeviceTime(deviceTimezone, moment);
884+
var deviceOffsetSeconds = timeformat.getTimezoneOffsetSeconds(deviceTimezone, moment);
885+
886+
// Fall back to browser time if no device timezone
887+
if (!deviceTime) {
888+
deviceTime = new Date(client.now);
889+
}
890+
891+
// Check if we need to show both times (different UTC offsets)
892+
var showBothTimes = timeformat.shouldShowBothTimes(deviceOffsetSeconds);
893+
894+
if (showBothTimes) {
895+
var browserTime = new Date(client.now);
896+
$('#currentTime')
897+
.html(formatTime(deviceTime, true) + ' <span class="device-label">(Device)</span> <span class="local-time">' + formatTime(browserTime, true) + ' (Local)</span>')
898+
.css('text-decoration', '');
899+
900+
// Apply styles via CSS
901+
$('#currentTime .device-label').css({
902+
'font-size': '0.8em',
903+
'opacity': '0.7'
904+
});
905+
$('#currentTime .local-time').css({
906+
'font-size': '0.8em',
907+
'opacity': '0.6'
908+
});
909+
} else {
910+
$('#currentTime').text(formatTime(deviceTime, true)).css('text-decoration', '');
911+
}
878912
}
879913

880914
function getClientAlarm (level, group) {

lib/client/timeformat.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
'use strict';
2+
3+
/**
4+
* Shared timezone formatting utilities for displaying device and browser times
5+
*/
6+
7+
/**
8+
* Calculate timezone offset in seconds from a timezone string using moment-timezone
9+
* @param {string} timezone - Timezone string (e.g., "Etc/GMT-1")
10+
* @param {object} moment - moment-timezone instance
11+
* @returns {number|null} - Offset in seconds, or null if timezone is invalid
12+
*/
13+
function getTimezoneOffsetSeconds(timezone, moment) {
14+
if (!timezone || !moment || !moment.tz) {
15+
return null;
16+
}
17+
try {
18+
var deviceMoment = moment().tz(timezone);
19+
return deviceMoment.utcOffset() * 60; // Convert minutes to seconds
20+
} catch (err) {
21+
console.error('Error calculating timezone offset:', err);
22+
return null;
23+
}
24+
}
25+
26+
/**
27+
* Get current time in a specific timezone
28+
* @param {string} timezone - Timezone string (e.g., "Etc/GMT-1")
29+
* @param {object} moment - moment-timezone instance
30+
* @returns {Date|null} - Date object in device timezone, or null if timezone is invalid
31+
*/
32+
function getDeviceTime(timezone, moment) {
33+
if (!timezone || !moment || !moment.tz) {
34+
return null;
35+
}
36+
try {
37+
return moment().tz(timezone).toDate();
38+
} catch (err) {
39+
console.error('Error getting device time:', err);
40+
return null;
41+
}
42+
}
43+
44+
/**
45+
* Get browser timezone offset in seconds
46+
* @returns {number} - Browser timezone offset in seconds
47+
*/
48+
function getBrowserOffsetSeconds() {
49+
return -new Date().getTimezoneOffset() * 60;
50+
}
51+
52+
/**
53+
* Check if device and browser timezones have different UTC offsets
54+
* @param {number|null} deviceOffsetSeconds - Device timezone offset in seconds
55+
* @returns {boolean} - True if offsets differ
56+
*/
57+
function shouldShowBothTimes(deviceOffsetSeconds) {
58+
if (deviceOffsetSeconds === null) {
59+
return false;
60+
}
61+
var browserOffsetSeconds = getBrowserOffsetSeconds();
62+
return deviceOffsetSeconds !== browserOffsetSeconds;
63+
}
64+
65+
module.exports = {
66+
getTimezoneOffsetSeconds: getTimezoneOffsetSeconds,
67+
getDeviceTime: getDeviceTime,
68+
getBrowserOffsetSeconds: getBrowserOffsetSeconds,
69+
shouldShowBothTimes: shouldShowBothTimes
70+
};

0 commit comments

Comments
 (0)