Initial commit — Seth Calendar & Decimal Time clock site

Pages: /, /simple, /decimal, /seth, /calendar, /astro, /convert, /timegov
Features: Seth Calendar (10×36 + holidays), decimal time, moon phases,
astronomy (sun/moon), bidirectional time converter, Seth date display,
leap day split cell in calendar grid.
This commit is contained in:
2026-03-08 22:32:38 +00:00
commit a6b3f039d8
48 changed files with 7324 additions and 0 deletions
@@ -0,0 +1,126 @@
///////////////////////////////////////////////////////////////////////////
////////////////////// ANALOG CLOCK FUNCTIONS ///////////////////////////
///////////////// Clock code used from W3Schools.com ////////////////////
//////// Refer to their site about applicable use of the code ///////////
///////////////////////////////////////////////////////////////////////////
var canvas = document.getElementById("analog-clock");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90
setInterval(drawClock, 1000);
// add 0 to single digit time min, sec
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
function drawClock() {
drawFace(ctx, radius);
drawNumbers(ctx, radius);
drawTime(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2*Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0,0,radius*0.95, 0,0,radius*1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius*0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius*0.1, 0, 2*Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius*0.15 + "px arial";
ctx.textBaseline="middle";
ctx.textAlign="center";
for(num = 1; num < 13; num++){
ang = num * Math.PI / 6;
ctx.rotate(ang);
ctx.translate(0, -radius*0.85);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, radius*0.85);
ctx.rotate(-ang);
}
}
function drawTime(ctx, radius){
var deviceClock = new Date();
var hour = deviceClock.getHours();
var minute = deviceClock.getMinutes();
var second = deviceClock.getSeconds();
var ampm = hour >= 12 ? 'P.M.' : 'A.M.';
hour = hour % 12;
hour = hour ? hour : 12; // the hour '0' should be '12'
//minute = minute < 10 ? '0'+minute : minute;
// CHECKTIME FUNC ADDS LEADING '0' if <10
hour = checkTime(hour);
minute = checkTime(minute);
second = checkTime(second);
//digital time display
var myDigTime = hour + ":" + minute +":" + second;
document.getElementById('myTime').innerHTML = myDigTime + ' ' + ampm;
var dd = deviceClock.getDate();
var mm = deviceClock.getMonth();
mm++; //Increment because Jan is month 0
dd = checkTime(dd);
mm = checkTime(mm);
var yyyy = deviceClock.getFullYear();
var todaysDate = mm + '/' + dd + '/' + yyyy;
document.getElementById("myDate").innerHTML = "Today: " + todaysDate;
// OFFSET
var utcOffset = deviceClock.getTimezoneOffset()/60;
if (utcOffset > 0) {
utcOffset = "(UTC-" + utcOffset + ")";
} else {
utcOffset = "(UTC+" + Math.abs(utcOffset) + ")";
};
document.getElementById("myTimeTitle").innerHTML = utcOffset;
//hour
hour=hour%12;
hour=(hour*Math.PI/6)+
(minute*Math.PI/(6*60))+
(second*Math.PI/(360*60));
drawHand(ctx, hour, radius*0.5, radius*0.07);
//minute
minute=(minute*Math.PI/30)+(second*Math.PI/(30*60));
drawHand(ctx, minute, radius*0.8, radius*0.07);
// second
second=(second*Math.PI/30);
drawHand(ctx, second, radius*0.9, radius*0.02);
}
function drawHand(ctx, pos, length, width) {
ctx.beginPath();
ctx.lineWidth = width;
ctx.lineCap = "round";
ctx.moveTo(0,0);
ctx.rotate(pos);
ctx.lineTo(0, -length);
ctx.stroke();
ctx.rotate(-pos);
}
@@ -0,0 +1,67 @@
// ONLOAD OPERATIONS FOR THE SITE
window.onload = function() {
/* PARSE THE URL FOR 12/24 VARIABLE*/
var getT = location.search;
var tArr = getT.split("=");
var t = tArr[1];
// CREATE A VAR FOR THE CHECKBOX
var twentyFour = document.getElementById("twenty-four");
// CHECK VALUE OF 12/24 URL VAR "t" AND SET CHECKBOX ACCORDINGLY
if (t === "24") {
twentyFour.checked = true;
} else {
// DEFAULT TO 12HR DISPLAY
twentyFour.checked = false;
}
var noMoreAlerts = false;
// NOTIFICATION BOX FOR BOOKMARKING 24-HOUR SETTINGS PAGE
var twentyFour = document.getElementById("twenty-four");
twentyFour.addEventListener("click", function(event) {
var hourLabelDiv = document.getElementsByClassName("am-pm")[0];
var url = window.location.toString();
if(timeDotGov.data.twentyFour()) {
window.history.replaceState(url, "", "/timegov/?t=24");
if (!noMoreAlerts) {
alert("Bookmarking this page will save your preference for 24-hour time display.");
}
noMoreAlerts = true;
} else {
window.history.replaceState(url, "", "/timegov/");
}
timeDotGov.clockController.handleonrefresh(new Date());
});
//? timeZoneChange = function(event) {
//? timeDotGov.clockController.getnewOffset(event.target.value);
//? }
// LOAD DST DATES AND LEAP DATE
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", "/api/timegov/auxdata.xml", false); // false for synchronous request
xmlHttp.send(null);
timeDotGov.auxdata = xmlHttp.responseText;
timeDotGov.clockController.auxdata();
timeDotGov.clockController.checkservertime();
document.getElementById('responseTime').innerHTML = timeDotGov.data.zoneOffset;
// SET REFRESH RATE TO CHECK FOR TOP OF NEW SECOND, SO THE DISPLAY DOES NOT HAVE TO BE REFRESHED MORE THAN NECESSARY
setInterval(function() {
if(timeDotGov.data.currentTime) {
timeDotGov.clockController.runningclocks();
}
}, 20); // 20 milliseconds
// FUNCTION REFRESHES PAGE EVERY 10 MIN
setInterval(function() {
location.reload();
}, 600000);
};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,370 @@
timeDotGov = {};
timeDotGov.clock = {};
timeDotGov.clockController = {};
timeDotGov.clockController.dsClock = {}
timeDotGov.data = {
"then": null,
"serverTime": null,
"responseTime": null,
"RThalf": null,
"realTimeDif": null,
"requestTime": null,
"leapsecond": null,
"dststart": null,
"dstend": null,
"currYear": null,
"dstDates": null,
"leapDate": null,
"clockinstances": [],
"leapFlag": null,
"leapsec60": null,
"myhour0": "0",
"myhour1": "0",
"mysec0": "0",
"mysec1": "0",
"currentTime": null,
"twentyFour": function() {
twentyFour = document.getElementById("twenty-four");
return twentyFour.checked;
}
}
var offsetCheck = true;
var daylightTitles = false;
// CREATE ARRAY THAT WILL STORE WHICH CLOCK NUMS HAVE BEEN UPDATED
var dstClocksUpdated = [];
timeDotGov.clockController.getParameterByName = function(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
timeDotGov.clockController.getleapdate = function() {
var leap = new Date();
var temp1 = timeDotGov.data.leapdate.split(" ");
var leapdateYear = temp1[0];
var leapdateMonth = temp1[1];
leapdateMonth = leapdateMonth - 1; // month convention = 0-11 (Jan = 0)
var leapdateDay = temp1[2];
leap.setUTCFullYear(leapdateYear, leapdateMonth, leapdateDay);
leap.setUTCHours(0, 0, 0, 0);
timeDotGov.data.leapsecond = leap.getTime();
}
// GET TIME FROM SERVER
timeDotGov.clockController.dsClock.doRequest = function() {
d = new Date();
var xmlHttp = new XMLHttpRequest();
////////////////////////////////////////////////////////////////////////////////////
////// USE OF THIS .CGI BY OUTSIDE SITES OR APPLICATIONS IS STRICTLY PROHIBITED ////
// OR USING THE TIME FROM THIS SITE IN ANY WAY FOR OTHER SITES IS ALSO PROHIBITED //
///////////////////////////////////////////////////////////////////////////////////
xmlHttp.open("GET", "/zzz__2fbc6c3300df7e4483acd44c5044098a9fcc61d6.cgi?disablecache=" + d.getTime(), false);
xmlHttp.send(null);
return xmlHttp.responseText;
}
// GET t1, t2, t3, t4 in doRequest AND CALCULATE DELAYS IN doData
timeDotGov.clockController.checkservertime = function() {
var o = new Object();
var d = new Date();
var currentTimeObj = new Date();
timeDotGov.data.requestTime = currentTimeObj.getTime();
timeDotGov.data.currentTime = timeDotGov.clockController.dsClock.doRequest(); // GET NIST TIME FROM SERVER
timeDotGov.clockController.doData();
}
// PARSE DATA FROM AUXDATA.XML
timeDotGov.clockController.doAuxData = function() {
parser = new DOMParser();
xmlDoc = parser.parseFromString(timeDotGov.auxdata, "text/xml");
timeDotGov.data.curryear = xmlDoc.getElementsByTagName("currYear")[0].childNodes[0].nodeValue;
timeDotGov.data.dstdates = xmlDoc.getElementsByTagName("DstDates")[0].childNodes[0].nodeValue;
timeDotGov.data.leapdate = xmlDoc.getElementsByTagName("LeapDate")[0].childNodes[0].nodeValue;
}
timeDotGov.clockController.getDSTdates = function() {
var dstStartDate = new Date();
var dstEndDate = new Date();
var temp=timeDotGov.data.dstdates.split(" "); // makes an array of the string elements
var startmonth = temp[0];
startmonth = startmonth - 1; // to follow js convention of month = 0-11 (Jan = 0)
var startday = temp[1];
var endmonth = temp[2];
endmonth = endmonth - 1;
var endday = temp[3];
dstStartDate.setUTCFullYear(timeDotGov.data.curryear, startmonth, startday);
dstStartDate.setUTCHours(2, 0, 0, 0);
dstEndDate.setUTCFullYear(timeDotGov.data.curryear, endmonth, endday);
dstEndDate.setUTCHours(1, 0, 0, 0);
timeDotGov.data.dstStart = dstStartDate.getTime();
timeDotGov.data.dstEnd = dstEndDate.getTime();
}
timeDotGov.clockController.auxdata = function() {
this.doAuxData();
this.getDSTdates();
this.getleapdate();
}
timeDotGov.clockController.doData = function() {
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(timeDotGov.data.currentTime, "text/xml");
var t2 = xmlDoc.getElementsByTagName("timestamp")[0].getAttribute("time2");
var t3 = xmlDoc.getElementsByTagName("timestamp")[0].getAttribute("time3");
var serverDelay = Math.round((t3 - t2) / 1000); // server delay in milliseconds
timeDotGov.data.serverTime = Math.round(t3/1000); // Server time in milliseconds
var currentTimeObj2 = new Date();
timeDotGov.data.responseTime = currentTimeObj2.getTime(); // t4
timeDotGov.data.RThalf = ((timeDotGov.data.responseTime - timeDotGov.data.requestTime) - serverDelay) / 2; // (t4 - t1) - (t3 -t2) NTP EQ
timeDotGov.data.realTimeDif = timeDotGov.data.serverTime - timeDotGov.data.responseTime; // t3-t4 used for correction to local clock for official time
////////////////////////////////////////////////////////////
// USE OFFSET CHECK VAR TO ONLY CHECK CLIENT CLOCK ONCE ///
////////////////////////////////////////////////////////////
if (offsetCheck) {
// ROUND TO MILLISECONDS - USE (* -1) to invert timediff pos/neg display value
var diff = (timeDotGov.data.realTimeDif/1000) * -1;
var diffDisplay = diff.toFixed(3);
if (diffDisplay > 0 ) {
diffDisplay = "+" + diffDisplay;
}
document.getElementById("realTimeDif").innerHTML = diffDisplay;
offsetCheck = false;
}
timeDotGov.clockController.runningclocks();
timeDotGov.data.leapFlag = "false";
} // END OF doData FUNCTION
// REFRESHES CLOCKS AT THE TOP OF EACH *ACTUAL* SECOND
timeDotGov.clockController.runningclocks = function() {
var deviceClock = new Date();
var fractionalZone =(Math.abs((deviceClock.getTimezoneOffset()/60))) % 1; // IF CLIENT IS IN A ZONE WITH A FRACTIONAL HOUR, MAKE ADJUSTMENT (MODULO 1 TO GET THE FRACTIONAL HOUR)
if (fractionalZone != 0) {
fractionalZone = (1 - fractionalZone); // SUBTRACT FROM 1 TO GET VALID CORRECTION FOR 30 AND 45 MIN ZONES
}
var fractionalZoneMilli = fractionalZone * 3600000; // CONVERT PARTIAL HOUR TO MILLISECONDS, TO BE SUBTRACTED FROM ADJUSTED TIME
var s = new Date(); // convert PC time and delay back to seconds (this is UTC)
s.setTime(s.getTime() + timeDotGov.data.realTimeDif + timeDotGov.data.RThalf - fractionalZoneMilli); // CORRECT FOR PC CLOCK ERROR, HALF NETWORK DELAY AND CLIENT IN PARTIAL TIME ZONE
var sec = s.getSeconds();
if (sec != timeDotGov.data.previousSec) { // call handleonrefresh as soon as you see a new second
timeDotGov.data.previousSec = sec;
timeDotGov.clockController.handleonrefresh(s);
}
}
// CHECK IF USER CHANGED CLOCK or IF NEW DST STATE or LEAP SECOND, THEN REFRESH ALL CLOCKS
timeDotGov.clockController.handleonrefresh = function(s) {
//var mins = s.getMinutes();
var now = s.getTime(); // convert time to ms since epoch (UTC)
//if (0 <= mins < 30) {
// now = now + fractionalZoneMilli;
//} else {
// now = now - fractionalZoneMilli;
//}
if (timeDotGov.data.then == null) {
timeDotGov.data.then = now; // if it's the first round, don't let it fail
}
var DidUserChangeClock = Math.abs(now - timeDotGov.data.then);
if (DidUserChangeClock >= 2000) { // if pc clock changed then reset (|now-then| should only be 1 s)
location.reload();
timeDotGov.data.then = now;
} else {
timeDotGov.data.then = now;
}
if (timeDotGov.data.leapsecond / 1000 == Math.floor(now / 1000)) {
timeDotGov.data.leapFlag = "true"
}
var clocks = document.getElementsByClassName("clock");
var clockNum; // SET TO VALUE OF 'i' IN THE FOLLOWING LOOP TO REPRESENT EACH CLOCK INSTANCE
// SET ALL OF THE CLOCKS BY CALLING setCurrentTime FOR EACH CLOCK INSTANCE
for(var i =0; i < clocks.length; i++ ){
var clock = clocks[i].getElementsByTagName("time")[0];
var zoneOffset = clocks[i].getElementsByTagName("time")[0].getAttribute("zoneOffset") || 0;
// GIVE VAR CLOCKNUM VALUE OF i
clockNum = i;
clock.innerHTML = timeDotGov.clock.setCurrentTime(timeDotGov.data.clockinstances[i], now, timeDotGov.data.twentyFour(), timeDotGov.data.dstStart, timeDotGov.data.dstEnd, zoneOffset, timeDotGov.data.leapFlag, timeDotGov.data.leapsec60, timeDotGov.data.RThalf, clockNum);
document.getElementById('timeUTC').innerHTML = timeDotGov.clock.setCurrentTime(timeDotGov.data.clockinstances[i], now, true, timeDotGov.data.dstStart, timeDotGov.data.dstEnd, 0, timeDotGov.data.leapFlag, timeDotGov.data.leapsec60, timeDotGov.data.RThalf, 999); // LAST VAR IS CLOCKNUM, PASSING AS '999' TO AVOID DUPLICATE 'i' VARIABLE VALUE SEND TO SETCURRENTTIME FUNCTION
}
} // END OF handleonrefresh FUNCTION
// CREATES CLOCK DIGITS AND DST/ST LABELS FOR EACH CLOCK INSTANCE
timeDotGov.clock.setCurrentTime = function(clock, now, twentyFour, dstStart, dstEnd, zoneOffset, leapFlag, leapsec60, RThalf, clockNum) {
var displayTime = new Date();
now = (now - (zoneOffset * 3600000));
if (leapFlag == "true"){
now = now - 1000; // if leap has occurred, show (seconds - 1) until next sync
var leapsec60 = "true"; // var to show a 60 instead of 59
}
displayTime.setTime(now);
var year = displayTime.getUTCFullYear();
var hourNum = displayTime.getUTCHours();
var minNum = displayTime.getMinutes();
var secNum = displayTime.getSeconds();
// CREATE ARRAY OF THE CLOCK NUMS WHO FOLLOW DST
// ALSO CREATE ARRAY OF DST LABEL CLASSES ////////////////////////
var DSTclocksArray = [ 0, 1, 6, 7, 8, 9 ]; // THESE ARE THE clockNums FOR THE ZONES THAT FOLLOW DST
var dstLabels = document.getElementsByClassName("DSTterm"); // CREATE ARRAY FOR DST LABELS
var dstLetters = document.getElementsByClassName("DSTletter"); // CREATE ARRAY FOR DST ABBREVIATION
var dstNums = document.getElementsByClassName("DSTnum"); // CREATE ARRAY FOR DST OFFSET NUM
if ( now >= dstStart && now <= dstEnd ) { // CHECK IF THIS SECOND IS DST OR NOT
// CHECK IF CLOCK NUM IS IN DST ARRAY, IF SO, ADD THE DST HOUR AND LABELS
// if ( DSTclocksArray.includes(clockNum) ) {
if ( DSTclocksArray.indexOf(clockNum) > -1 ) { // indexOf fixes a chance in ie
hourNum = hourNum + 1;
// AT END OF FUNC ADD/PUSH CLOCKNUM TO dstClocksUpdated ARRAY, IF CLOCKNUM IS IN THERE, DONT UPDATE AGAIN
// if ( !dstClocksUpdated.includes( clockNum ) ) {
if ( dstClocksUpdated.indexOf( clockNum ) == -1 ) { // indexOf fixes a chance in ie
dstLabels[clockNum].innerHTML = "DAYLIGHT";
dstLetters[clockNum].innerHTML = "D";
var standardNum = Number(dstNums[clockNum].innerHTML);
dstNums[clockNum].innerHTML = standardNum - 1;
dstClocksUpdated.push(clockNum); // ADD CLOCK NUM TO ARRAY OF CLOCKS UPDATED
}
}
}
// IF DST OR INCREMENTED HOUR GOES INTO NEXT DAY, RESET TO HOUR ZERO AND ADD A DAY
if (hourNum > 23) {
hourNum = 0;
now = (now + 3600000) // advance now by one hour
displayTime.setTime(now); // reset displaytime so day/date/month are correct with new day
}
// CHECK FOR AND IMPLEMENT LEAP SECOND
if (leapFlag == "true") {
if (leapsec60 == "true") {
if (minNum == "59") {
if (secNum == "59") { // if leapsec, and 59:59 then show 60 and reset
secNum = "60";
leapsec60 = "false";
}
}
}
}
var hourLabel = "";
// 12-HOUR OR 24-HOUR DISPLAY
// BOX NOT CHECKED SO 12-HOUR DISPLAY
if (!(twentyFour)) {
if (hourNum > 11) {
hourNum -= 12;
am_pm = "P.M.";
} else {
am_pm = "A.M.";
}
} else {
am_pm = "";
}
var newVal;
// SET HOURS
if(hourNum > 9) {
newVal = Number(String(hourNum).charAt(0));
if(timeDotGov.data.myhour0 != newVal) {
timeDotGov.data.myhour0 = newVal;
}
}
else if(Number(timeDotGov.data.myhour0) != 0) {
timeDotGov.data.myhour0 = "0";
}
if(Number(hourNum) > 9){
newVal=Number(String(hourNum).charAt(1));
if(timeDotGov.data.myhour1 != newVal) {
timeDotGov.data.myhour1 = newVal;
}
} else if (Number(timeDotGov.data.myhour1) != Number(hourNum)) {
timeDotGov.data.myhour1 = Number(hourNum);
}
if ((hourNum < 1) && (!(twentyFour))) { // if not 24hour time force the 12 so it's not 00
timeDotGov.data.myhour0 = 1;
timeDotGov.data.myhour1 = 2;
}
// SET MINUTES
if(minNum > 9) {
newVal = Number(String(minNum).charAt(0));
if (timeDotGov.data.mymin0 != newVal) {
timeDotGov.data.mymin0 = newVal;
}
} else if(Number(timeDotGov.data.mymin0) != 0) {
timeDotGov.data.mymin0 = 0;
}
if(Number(minNum) > 9) {
newVal = Number(String(minNum).charAt(1));
if(timeDotGov.data.mymin1 != newVal) {
timeDotGov.data.mymin1 = newVal;
}
}
else if(Number(timeDotGov.data.mymin1) != Number(minNum)) {
timeDotGov.data.mymin1 = Number(minNum);
}
// SET SECONDS
if(secNum > 9) {
newVal = Number(String(secNum).charAt(0));
if(timeDotGov.data.mysec0 != newVal) {
timeDotGov.data.mysec0 = newVal;
}
}
else if(Number(timeDotGov.data.mysec0) != 0) {
timeDotGov.data.mysec0 = 0;
}
if(Number(secNum) > 9) {
newVal=Number(String(secNum).charAt(1));
if(timeDotGov.data.mysec1 != newVal) {
timeDotGov.data.mysec1 = newVal;
}
}
else if(Number(timeDotGov.data.mysec1) != Number(secNum)) {
timeDotGov.data.mysec1 = Number(secNum);
}
// CREATE CLOCK DIGITS STRING TO DISPLAY
var clockdigits = (timeDotGov.data.myhour0 + "" + timeDotGov.data.myhour1 + ":" + timeDotGov.data.mymin0 + timeDotGov.data.mymin1 + ":" + timeDotGov.data.mysec0 + timeDotGov.data.mysec1);
clock = clockdigits + " " + am_pm;
return clock;
} // END OF setCurrentTime FUNCTION