diff --git a/ctrl/main.ini b/ctrl/main.ini
index 679214a520c0617e3ea34cd3c2d75107778ec663..bdd23fb656fe3a231ac26837c45167c84879e9eb 100644
--- a/ctrl/main.ini
+++ b/ctrl/main.ini
@@ -6,7 +6,7 @@ operator=Sysop
 guru=The Guru
 password=SYSPASS
 password_timeout=15
-timezone=0
+timezone=-1
 settings=0x611f848
 date_fmt=0
 date_sep=/
diff --git a/src/sbbs3/js_system.c b/src/sbbs3/js_system.c
index 17a2a956e2026fb445e9e4542ca53ad8ebd6e223..52e63127155c1f583a0195cb82a9fcd04debda73 100644
--- a/src/sbbs3/js_system.c
+++ b/src/sbbs3/js_system.c
@@ -167,12 +167,10 @@ static JSBool js_system_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 			p=cfg->sys_location;
 			break;
 		case SYS_PROP_TIMEZONE:
-			sys_timezone(cfg);
-			*vp = INT_TO_JSVAL(cfg->sys_timezone);
+			*vp = INT_TO_JSVAL(sys_timezone(cfg));
 			break;
 		case SYS_PROP_TZ_OFFSET:
-			sys_timezone(cfg);
-			*vp = INT_TO_JSVAL(smb_tzutc(cfg->sys_timezone));
+			*vp = INT_TO_JSVAL(smb_tzutc(sys_timezone(cfg)));
 			break;
 		case SYS_PROP_NODES:
 			*vp = INT_TO_JSVAL(cfg->sys_nodes);
diff --git a/src/sbbs3/load_cfg.c b/src/sbbs3/load_cfg.c
index 1a87d59715156790ee646bcfe701fcf9e8042e53..77dedc45c02ad752a8cfbc08dc1e6f084cec8b92 100644
--- a/src/sbbs3/load_cfg.c
+++ b/src/sbbs3/load_cfg.c
@@ -24,6 +24,7 @@
 #include "str_util.h"
 #include "nopen.h"
 #include "datewrap.h"
+#include "xpdatetime.h"
 #include "text.h"	/* TOTAL_TEXT */
 #include "ini_file.h"
 #if defined(SBBS) && defined(USE_CRYPTLIB)
@@ -534,6 +535,9 @@ ushort sys_timezone(scfg_t* cfg)
 	time_t	now;
 	struct tm tm;
 
+	if(cfg->sys_timezone == SYS_TIMEZONE_AUTO)
+		return xpTimeZone_local();
+
 	if(cfg->sys_misc&SM_AUTO_DST && SMB_TZ_HAS_DST(cfg->sys_timezone)) {
 		now=time(NULL);
 		if(localtime_r(&now,&tm)!=NULL) {
diff --git a/src/sbbs3/scfg/scfgsys.c b/src/sbbs3/scfg/scfgsys.c
index ce233c48bf868ec0715ed8bc6ae9f8ecb7b36304..c02550597696e17ff9f06ddd335e9c66a0772c11 100644
--- a/src/sbbs3/scfg/scfgsys.c
+++ b/src/sbbs3/scfg/scfgsys.c
@@ -185,6 +185,10 @@ static int configure_dst(int page, int total)
 	return i;
 }
 
+#define UTC_OFFSET_HELP \
+		"The UTC offset alone can be ambiguous as some time zones share the same\n" \
+		"offset from UTC as other time zones for some or all months of the year.\n"
+
 int edit_sys_timezone(int page, int total)
 {
 	int mode = WIN_SAV | WIN_MID;
@@ -192,6 +196,32 @@ int edit_sys_timezone(int page, int total)
 	int i;
 	int bar;
 
+	i = cfg.sys_timezone != SYS_TIMEZONE_AUTO;
+	uifc.helpbuf=
+		"`Automatically Determine Time Zone:`\n"
+		"\n"
+		"Query the operating system for the current local time zone as an offset\n"
+		"(i.e. minutes east or west) from UTC.\n"
+		"\n"
+		UTC_OFFSET_HELP
+		"\n"
+		"If enabled, this query will occur automatically each time the local time\n"
+		"zone is needed, so any affect of daylight saving time will be applied\n"
+		"automatically as well.\n"
+	;
+	if(page)
+		mode = wiz_help(page, total, uifc.helpbuf);
+	i = uifc.list(mode, 0, 15, 0, &i, 0
+		,"Automatically Determine Time Zone (as offset from UTC)"
+		,uifcYesNoOpts);
+	if(i==-1)
+		return -1;
+	if(i==0) {
+		cfg.sys_timezone = SYS_TIMEZONE_AUTO;
+		return 0;
+	}
+	if(cfg.sys_timezone == SYS_TIMEZONE_AUTO)
+		cfg.sys_timezone = 0;
 	i = OTHER_ZONE(cfg.sys_timezone) || !(cfg.sys_timezone & US_ZONE);
 	uifc.helpbuf=
 		"`United States Time Zone:`\n"
@@ -430,6 +460,8 @@ int edit_sys_timezone(int page, int total)
 				"\n"
 				"Enter your local time zone offset from Universal Time (UTC/GMT) in\n"
 				"`HH:MM` format.\n"
+				"\n"
+				UTC_OFFSET_HELP
 			;
 			if(page)
 				mode = wiz_help(page, total, uifc.helpbuf);
@@ -1705,8 +1737,9 @@ void sys_cfg(void)
 		i=0;
 		snprintf(opt[i++],MAX_OPLN,"%-20s%s","BBS Name",cfg.sys_name);
 		snprintf(opt[i++],MAX_OPLN,"%-20s%s","Location",cfg.sys_location);
-		snprintf(opt[i++],MAX_OPLN,"%-20s%s %s","Local Time Zone"
-			,smb_zonestr(cfg.sys_timezone,NULL)
+		snprintf(opt[i++],MAX_OPLN,"%-20s%s%s %s","Local Time Zone"
+			,cfg.sys_timezone == SYS_TIMEZONE_AUTO ? "Auto: " : ""
+			,smb_zonestr(sys_timezone(&cfg),NULL)
 			,SMB_TZ_HAS_DST(cfg.sys_timezone) && cfg.sys_misc&SM_AUTO_DST ? "(Auto-DST)" : "");
 		snprintf(opt[i++],MAX_OPLN,"%-20s%s (e.g. %s)","Short Date Format"
 			,date_format(&cfg, str, sizeof str)
diff --git a/src/sbbs3/scfgdefs.h b/src/sbbs3/scfgdefs.h
index e9fcaf3431a32dcb4c0a2e325122c159ec998d7d..c4df44680a5e8bdec05c51142e58b26fc33e0b06 100644
--- a/src/sbbs3/scfgdefs.h
+++ b/src/sbbs3/scfgdefs.h
@@ -466,6 +466,7 @@ typedef struct
 	char 			sys_id[LEN_QWKID+1];/* System ID for QWK Packets */
 	char 			sys_inetaddr[128];	/* System's internet address */
 	char 			sys_location[41];	/* System Location */
+#define SYS_TIMEZONE_AUTO -1
 	int16_t			sys_timezone;		/* Time Zone of BBS */
 	enum date_fmt	sys_date_fmt;
 	char			sys_date_sep;
diff --git a/web/root/rss.ssjs b/web/root/rss.ssjs
deleted file mode 100644
index 195ce6fea8bf81915aea1acb24121364b8d50f70..0000000000000000000000000000000000000000
--- a/web/root/rss.ssjs
+++ /dev/null
@@ -1,204 +0,0 @@
-// rss.ssjs
-
-// $Id: rss.ssjs,v 1.22 2016/10/20 19:13:38 rswindell Exp $
-
-// Tested successfully with SharpReader v0.9.5.1
-
-load("sbbsdefs.js");
-
-var REVISION = "$Revision: 1.22 $".split(' ')[1];
-
-//log(LOG_INFO,"Synchronet RSS " + REVISION);
-
-var link_root = "http://" + http_request.header.host + http_request.request_string;
-
-var ini_fname = file_cfgname(system.ctrl_dir, "rss.ini");
-
-var ini_file = new File(ini_fname);
-if(!ini_file.open("r")) {
-	log(LOG_ERR,format("!ERROR %d opening ini_file: %s"
-		,ini_file.error, ini_fname));
-	exit();
-}
-
-var channel_list = ini_file.iniGetAllObjects();
-var defaults = ini_file.iniGetObject();
-
-ini_file.close();
-
-/* Set default max from the NetScapes original RSS 0.91 implementation
-http://my.netscape.com/publish/formats/rss-spec-0.91.html#item */
-
-if(defaults.maxmessages==undefined)
-	defaults.maxmessages=15;
-
-if(defaults.maxdesclength==undefined)
-	defaults.maxdesclength=500;
-
-var channel;
-for(c in channel_list)
-    if(channel_list[c].name == http_request.query["channel"]) {
-        channel=channel_list[c];
-        break;
-    }
-
-if(channel==undefined) {
-	writeln('<html>');
-	writeln('<body>');
-	writeln('<h1>' + system.name + " News (RSS) Channels" + '</h1>');
-	writeln('<ul>');
-	for(c in channel_list)
-		writeln('<li>' 
-			+ channel_list[c].name.link(link_root + "?channel=" + channel_list[c].name));
-	writeln('</ul>');
-	writeln('</body>');
-	writeln('</html>');
-	exit();
-}
-
-var sub = msg_area.sub[channel.sub.toLowerCase()];
-if(sub==undefined) {
-    writeln(log(LOG_ERR,"!unknown sub-board: " + channel.sub));
-	exit();
-}
-
-if(http_request.query["item"]) {
-
-	load("../web/lib/template.ssjs");
-	load("../web/lib/mime_decode.ssjs");
-
-	var msgbase=new MsgBase(channel.sub);
-	if(!msgbase.open())
-		writeln(log(LOG_ERR,'Error: ' + msgbase.error));
-	else {
-		template.hdr = msgbase.get_msg_header(false,Number(http_request.query["item"]));
-		if(!template.hdr)
-			writeln(log(LOG_ERR,'Error: ' + msgbase.error));
-		else
-			template.body= msgbase.get_msg_body(false, template.hdr.number);
-	}
-
-	msg=mime_decode(template.hdr,template.body);
-	template.body=msg.body;
-	if(msg.type=="plain") {
-		/* ANSI */
-		if(template.body.indexOf('\x1b[')>=0 || template.body.indexOf('\x01')>=0) {
-			template.body=html_encode(template.body,true,false,true,true);
-		}
-		/* Plain text */
-		else {
-			template.body=word_wrap(template.body);
-			template.body=html_encode(template.body,true,false,false,false);
-		}
-	}
-	if(msg.attachments!=undefined) {
-		template.attachments=new Object;
-		for(att in msg.attachments) {
-			template.attachments[att]=new Object;
-			template.attachments[att].name=msg.attachments[att];
-		}
-	}
-
-	write_template("header.inc");
-	write_template("msgs/msg.inc");
-	write_template("footer.inc");
-
-	if(0) {
-	writeln('<html>');
-	writeln('<body>');
-	var msgbase=new MsgBase(channel.sub);
-	if(!msgbase.open())
-		writeln(log(LOG_ERR,'Error: ' + msgbase.error));
-	else {
-		var hdr = msgbase.get_msg_header(false,Number(http_request.query["item"]));
-		if(!hdr)
-			writeln(log(LOG_ERR,'Error: ' + msgbase.error));
-		else {
-			for(h in hdr)
-				writeln(h + ": " + hdr[h] + '<br>');
-		}
-	}
-	writeln('</body>');
-	writeln('</html>');
-	}
-
-	exit();
-}
-
-/* Setup default values (over-rideable in rss.ini) */
-if(channel.title==undefined)		channel.title			=sub.name;
-if(channel.description==undefined)	channel.description		=sub.description;
-if(channel.link==undefined)			channel.link			=link_root;
-if(channel.language==undefined)		channel.language		='en-us';
-
-if(channel.image_url==undefined)	channel.image_url		='/images/default/sync_pbgj1_white_bg.gif';
-if(channel.image_title==undefined)	channel.image_title		=channel.title;
-if(channel.image_link==undefined)	channel.image_link		=channel.link;
-if(channel.maxmessages==undefined)	channel.maxmessages		=defaults.maxmessages;
-if(channel.maxdesclength==undefined)	channel.maxdesclength		=defaults.maxdesclength;
-
-http_reply.header["Content-Type"]='application/rss+xml';
-writeln('<?xml version="1.0" ?>');
-writeln('<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" "http://my.netscape.com/publish/formats/rss-0.91.dtd">');
-writeln('<rss version="0.91">');
-writeln('\t<channel>');
-writeln('\t\t<title>'		+ channel.title			+ '</title>');
-writeln('\t\t<description>' + channel.description	+ '</description>');
-writeln('\t\t<link>'		+ channel.link			+ '</link>');
-writeln('\t\t<language>'	+ channel.language		+ '</language>');
-writeln('\t\t<image>');
-	writeln('\t\t\t<url>'	+ channel.image_url		+ '</url>');
-	writeln('\t\t\t<title>'	+ channel.image_title	+ '</title>');
-	writeln('\t\t\t<link>'	+ channel.image_link	+ '</link>');
-writeln('\t\t</image>');
-
-function encode(str, wspace)
-{
-	return(html_encode(strip_ctrl(str.replace(/\s+/g," "))
-		,true	/* ex-ASCII */
-		,wspace	/* white-space */
-		,false	/* ANSI */
-		,false	/* Ctrl-A */
-		));
-}
-
-var msgbase=new MsgBase(channel.sub);
-if(msgbase.open()) {
-
-	var last_msg;
-	var msgs=0;
-
-	if(last_msg = msgbase.get_msg_header(false, msgbase.last_msg)) {
-		writeln('\t\t<lastBuildDate>' + last_msg.date + '</lastBuildDate>');
-	}
-	var total_msgs = msgbase.total_msgs;
-	for(i=0;i<total_msgs;i++) {
-		var hdr = msgbase.get_msg_header(true,total_msgs-i);
-		if(!hdr || hdr.attr&MSG_DELETE)
-			continue;
-		var body = msgbase.get_msg_body(true,total_msgs-i);
-		body=body.replace(/\r\n/g,'<br />');
-		if(!body)
-			continue;
-		writeln('\t\t\t<item>');
-		writeln('\t\t\t\t<pubDate>' + hdr.date + '</pubDate>');
-		writeln('\t\t\t\t<title>' + encode(hdr.subject) + '</title>');
-		writeln('\t\t\t\t<author>' + encode(hdr.from) + '</author>');
-		writeln('\t\t\t\t<guid>' + encode(hdr.id) + '</guid>');
-		writeln('\t\t\t\t<description>' + encode(body.slice(0,channel.maxdesclength)) + '</description>');
-
-        if(this.login==undefined)  // v3.12a 
-            writeln('\t\t\t\t<link>' + link_root + (defaults.useentities ? '&amp;' : '&') + 'item=' + hdr.number + '</link>');
-        else    // v3.12b
-            writeln('\t\t\t\t<link>' + 'http://' + http_request.header.host + '/msgs/msg.ssjs?msg_sub=' + 
-                    channel.sub + (defaults.useentities ? '&amp;' : '&') + 'message=' + hdr.number + '</link>');
-		writeln('\t\t\t</item>');
-		msgs++;
-		if(msgs>=channel.maxmessages)
-			break;
-	}
-    msgbase.close();
-}
-writeln('\t</channel>');
-writeln('</rss>');
-