diff --git a/CHANGES.md b/CHANGES.md index 89d2737b..ac50f223 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,10 +1,13 @@ ### 0.x.x (2014-12-xx xx:xx:xx UTC) -* Add network logo's for BBC Canada, Crackle, El Rey Network, SKY Atlantic, and Watch +* Add network logos BBC Canada, Crackle, El Rey Network, SKY Atlantic, and Watch * Change Yahoo! screen network logo -* Change added and updated Discovery Network's channel logo's -* Remove unrequired duplicate network logo's -* Add Discovery Network International/A&E Network International/Scripps Networks International missing channel logos +* Add and update Discovery Network's channel logos +* Add A&E Network International/Scripps Networks International channel logos +* Remove non required duplicate network logos +* Add lowercase PM to the General Config/Interface/Time style selection +* Change General Config/Interface/Trim zero padding to Trim date and time, now handles 2:00 pm > 2 pm +* Fix trim zero of military time hour to not use 12 hr time [develop changelog] diff --git a/gui/slick/css/dark.css b/gui/slick/css/dark.css index b78b3bc9..01402916 100644 --- a/gui/slick/css/dark.css +++ b/gui/slick/css/dark.css @@ -1375,11 +1375,6 @@ config*.tmpl padding: 12px 0px; } -#config div.field-pair input { - float: left; - margin-right: 6px; -} - #config .nocheck, #config div #customQuality, .metadataDiv { padding-left: 20px; } diff --git a/gui/slick/css/light.css b/gui/slick/css/light.css index 416ec481..b5b79722 100644 --- a/gui/slick/css/light.css +++ b/gui/slick/css/light.css @@ -1358,11 +1358,6 @@ config*.tmpl padding: 12px 0px; } -#config div.field-pair input { - float: left; - margin-right: 6px; -} - #config .nocheck, #config div #customQuality, .metadataDiv { padding-left: 20px; } diff --git a/gui/slick/css/style.css b/gui/slick/css/style.css index 7c00de52..bd02c682 100644 --- a/gui/slick/css/style.css +++ b/gui/slick/css/style.css @@ -153,7 +153,7 @@ inc_top.tmpl /* background: url("../images/bg.png") repeat 0 0 transparent; */ } -[class^="icon-"], +[class^="icon-"], [class*=" icon-"] { background-image: url("../images/glyphicons-halflings.png"); } @@ -1591,10 +1591,13 @@ config*.tmpl padding: 12px 0 } -.stepDiv .component-desc select, -.stepDiv .component-desc input, #config div.field-pair select, #config div.field-pair input { + margin-right: 6px; +} + +.stepDiv .component-desc select, +.stepDiv .component-desc input { margin-right: 15px; } @@ -3153,6 +3156,11 @@ span.token-input-delete-token { z-index: 0; background-image: url(../images/poster-dark.jpg) } + +.time-am-pm { + margin-left: 2px; +} + /* ======================================================================= jquery.confirm.css ========================================================================== */ diff --git a/gui/slick/interfaces/default/config_general.tmpl b/gui/slick/interfaces/default/config_general.tmpl index 02e2a74c..2817d0e0 100644 --- a/gui/slick/interfaces/default/config_general.tmpl +++ b/gui/slick/interfaces/default/config_general.tmpl @@ -103,9 +103,9 @@ as the default selection when adding new shows @@ -127,7 +127,7 @@ Show root directories

where the files of shows are located

- #include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_rootDirs.tmpl') +#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_rootDirs.tmpl')
@@ -246,10 +246,10 @@
@@ -259,16 +259,16 @@ Date style: @@ -279,11 +279,12 @@ Time style: - note: seconds are only shown on the History page + note: seconds are only shown on the History page @@ -450,9 +451,9 @@ Branch version:

select branch to use (restart required)

@@ -485,9 +486,9 @@ CPU throttling: Normal (default). High is lower and Low is higher CPU use diff --git a/gui/slick/js/config.js b/gui/slick/js/config.js index e908b0f8..41046e69 100644 --- a/gui/slick/js/config.js +++ b/gui/slick/js/config.js @@ -1,85 +1,126 @@ $(document).ready(function(){ - $('.enabler').each(function(){ - if (!$(this).prop('checked')) - $('#content_' + $(this).attr('id')).hide(); - }); + var enabler = $('.enabler'), + viewIf = $('.viewIf'); - $('.enabler').click(function(){ - if ($(this).prop('checked')) - $('#content_' + $(this).attr('id')).fadeIn('fast', 'linear'); - else - $('#content_' + $(this).attr('id')).fadeOut('fast', 'linear'); - }); + enabler.each(function(){ + if (!$(this).prop('checked')) + $('#content_' + $(this).attr('id')).hide(); + }); - $('.viewIf').click(function(){ - if ($(this).prop('checked')) { - $('.hide_if_' + $(this).attr('id')).css('display','none'); - $('.show_if_' + $(this).attr('id')).fadeIn('fast', 'linear'); - } else { - $('.show_if_' + $(this).attr('id')).css('display','none'); - $('.hide_if_' + $(this).attr('id')).fadeIn('fast', 'linear'); - } - }); + enabler.click(function(){ + var content_id = $('#content_' + $(this).attr('id')); + if ($(this).prop('checked')) + content_id.fadeIn('fast', 'linear'); + else + content_id.fadeOut('fast', 'linear'); + }); - $('.datePresets').click(function(){ - var def = $('#date_presets').val() - if ($(this).prop('checked') && '%x' == def) { - def = '%a, %b %d, %Y' - $('#date_use_system_default').html('1') - } else if (!$(this).prop('checked') && '1' == $('#date_use_system_default').html()) - def = '%x' + viewIf.each(function(){ + $(($(this).prop('checked') ? '.hide_if_' : '.show_if_') + $(this).attr('id')).hide(); + }); - $('#date_presets').attr('name', 'date_preset_old') - $('#date_presets').attr('id', 'date_presets_old') + viewIf.click(function(){ + var if_id = '_if_' + $(this).attr('id'); + if ($(this).prop('checked')) { + $('.hide' + if_id).fadeOut('fast', 'linear'); + $('.show' + if_id).fadeIn('fast', 'linear'); + } else { + $('.show' + if_id).fadeOut('fast', 'linear'); + $('.hide' + if_id).fadeIn('fast', 'linear'); + } + }); - $('#date_presets_na').attr('name', 'date_preset') - $('#date_presets_na').attr('id', 'date_presets') + var ui_update_trim_zero = (function() { + var secs = ('00' + new Date().getSeconds().toString()).slice(-2), + elSecs = $('#trim_info_seconds'), + elTrimZero = $('#trim_zero'); + elTrimZero.each(function() { + var checked = $(this).prop('checked') && $('#fuzzy_dating').prop('checked'); - $('#date_presets_old').attr('name', 'date_preset_na') - $('#date_presets_old').attr('id', 'date_presets_na') + $('#time_presets').find('option').each(function() { + var text = ($(this).text()); + $(this).text(checked + ? text.replace(/(\b\d+:\d\d):\d+/mg, '$1') + : text.replace(/(\b\d+:\d\d)(?:.\d+)?/mg, '$1:' + secs)); + }); + }); - if (def) - $('#date_presets').val(def) - }); + if ($('#fuzzy_dating').prop('checked')) + if (elTrimZero.prop('checked')) + elSecs.fadeOut('fast', 'linear'); + else + elSecs.fadeIn('fast', 'linear'); + else + elSecs.fadeIn('fast', 'linear'); + }); - // bind 'myForm' and provide a simple callback function - $('#configForm').ajaxForm({ - beforeSubmit: function(){ - $('.config_submitter').each(function(){ - $(this).attr('disabled', 'disabled'); - $(this).after(' Saving...'); - $(this).hide(); - }); - }, - success: function(){ - setTimeout('config_success()', 2000) - } - }); + $('#trim_zero, #fuzzy_dating').click(function() { + ui_update_trim_zero(); + }); - $('#api_key').click(function(){ $('#api_key').select() }); - $("#generate_new_apikey").click(function(){ - $.get(sbRoot + '/config/general/generateKey', - function(data){ - if (data.error != undefined) { - alert(data.error); - return; - } - $('#api_key').val(data); - }); - }); + ui_update_trim_zero(); - $('#branchCheckout').click(function(){ - url = sbRoot + '/home/branchCheckout?branch=' + $('#branchVersion').val(); - window.location.href = url; - }); + $('.datePresets').click(function(){ + var elDatePresets = $('#date_presets'), + defaultPreset = elDatePresets.val(); + if ($(this).prop('checked') && '%x' == defaultPreset) { + defaultPreset = '%a, %b %d, %Y'; + $('#date_use_system_default').html('1') + } else if (!$(this).prop('checked') && '1' == $('#date_use_system_default').html()) + defaultPreset = '%x'; + + elDatePresets.attr('name', 'date_preset_old'); + elDatePresets.attr('id', 'date_presets_old'); + + var elDatePresets_na = $('#date_presets_na'); + elDatePresets_na.attr('name', 'date_preset'); + elDatePresets_na.attr('id', 'date_presets'); + + var elDatePresets_old = $('#date_presets_old'); + elDatePresets_old.attr('name', 'date_preset_na'); + elDatePresets_old.attr('id', 'date_presets_na'); + + if (defaultPreset) + elDatePresets.val(defaultPreset) + }); + + // bind 'myForm' and provide a simple callback function + $('#configForm').ajaxForm({ + beforeSubmit: function(){ + $('.config_submitter').each(function(){ + $(this).attr('disabled', 'disabled'); + $(this).after(' Saving...'); + $(this).hide(); + }); + }, + success: function(){ + setTimeout('config_success()', 2000) + } + }); + + $('#api_key').click(function(){ $('#api_key').select() }); + $("#generate_new_apikey").click(function(){ + $.get(sbRoot + '/config/general/generateKey', + function(data){ + if (data.error != undefined) { + alert(data.error); + return; + } + $('#api_key').val(data); + }); + }); + + $('#branchCheckout').click(function(){ + window.location.href = sbRoot + '/home/branchCheckout?branch=' + $('#branchVersion').val(); + }); }); function config_success(){ - $('.config_submitter').each(function(){ - $(this).removeAttr('disabled'); - $(this).next().remove(); - $(this).show(); - }); - $('#email_show').trigger('notify'); + $('.config_submitter').each(function(){ + $(this).removeAttr('disabled'); + $(this).next().remove(); + $(this).show(); + }); + $('#email_show').trigger('notify'); } diff --git a/gui/slick/js/fuzzyMoment.js b/gui/slick/js/fuzzyMoment.js index dc81c399..ab319f94 100644 --- a/gui/slick/js/fuzzyMoment.js +++ b/gui/slick/js/fuzzyMoment.js @@ -11,152 +11,170 @@ */ function fuzzyMoment(fmConfig) { - var containerClass = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.containerClass)) ? '.fuzzydate' : fmConfig.containerClass), - dateWithTime = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dateHasTime)) ? false : !!fmConfig.dateHasTime), - dateFormat = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dateFormat)) ? '' : fmConfig.dateFormat), - timeFormat = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.timeFormat)) ? '' : fmConfig.timeFormat), - trimZero = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.trimZero)) ? false : !!fmConfig.trimZero), - dtGlue = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dtGlue)) ? '
' : fmConfig.dtGlue), - dtInline = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dtInline)) ? false : fmConfig.dtInline), + var containerClass = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.containerClass)) ? '.fuzzydate' : fmConfig.containerClass), + dateWithTime = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dateHasTime)) ? false : !!fmConfig.dateHasTime), + dateFormat = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dateFormat)) ? '' : fmConfig.dateFormat), + timeFormat = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.timeFormat)) ? '' : fmConfig.timeFormat), + trimZero = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.trimZero)) ? false : !!fmConfig.trimZero), + dtGlue = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dtGlue)) ? '
' : fmConfig.dtGlue), + dtInline = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dtInline)) ? false : fmConfig.dtInline), - jd = (function (str) { - var token_map = ['a', 'ddd', 'A', 'dddd', 'b', 'MMM', 'B', 'MMMM', 'd', 'DD', 'm', 'MM', 'y', 'YY', 'Y', 'YYYY', 'x', 'L', - 'H', 'HH', 'I', 'hh', 'M', 'mm', 'S', 'ss', 'p', 'A'], - result = ''; + jd = (function (str) { + var token_map = ['a', 'ddd', 'A', 'dddd', 'b', 'MMM', 'B', 'MMMM', 'd', 'DD', 'm', 'MM', 'y', 'YY', 'Y', 'YYYY', 'x', 'L', + 'H', 'HH', 'I', 'hh', 'M', 'mm', 'S', 'ss', 'p', 'A', 'P', 'a'], + result = ''; - for (var i = 0; i < str.length; i++) - if (/[aAbBdmyYxHIMSp]/.test(str[i])) { - for (var t = 0; t < token_map.length; t = t + 2) - if (str[i] == token_map[t]) { - result += token_map[t + 1]; - break; - } - } else if ('%' != str[i]) - result += str[i]; + for (var i = 0; i < str.length; i++) + if (/[aAbBdmyYxHIMSpP]/.test(str[i])) { + for (var t = 0; t < token_map.length; t = t + 2) + if (str[i] == token_map[t]) { + result += token_map[t + 1]; + break; + } + } else if ('%' != str[i]) + result += str[i]; - return result; - }), - dateToken = jd(dateFormat), - timeToken = jd(timeFormat), + return result; + }), + dateTemplate = jd(dateFormat), + timeTemplate = jd(timeFormat), - addQTip = (function() { - $(this).css('cursor', 'help'); - $(this).qtip({ - show: { - solo: true - }, - position: { - viewport: $(window), - my: 'left center', - adjust: { - y: -10, - x: 2 - } - }, - style: { - classes: 'qtip-dark qtip-rounded qtip-shadow' - } - }); - }); + addQTip = (function() { + $(this).css('cursor', 'help'); + $(this).qtip({ + show: { + solo: true + }, + position: { + viewport: $(window), + my: 'left center', + adjust: { + y: -10, + x: 2 + } + }, + style: { + classes: 'qtip-dark qtip-rounded qtip-shadow' + } + }); + }); - if (trimZero) { - timeToken = timeToken.replace(/hh/ig, 'h'); - dateToken = dateToken.replace(/\bDD\b/g, 'D'); - } + if (trimZero) { + timeTemplate = timeTemplate.replace(/hh/g, 'h'); + timeTemplate = timeTemplate.replace(/HH/g, 'H'); + dateTemplate = dateTemplate.replace(/\bDD\b/g, 'D'); + } - $(containerClass).each(function() { - var input = $(this).text(), - dateA = '[', - dtSeparator = ' ', - timeA = ']', timeB = '[' + timeA; + $(containerClass).each(function() { + var input = $(this).text(), + dateA = '[', + dtSeparator = ' ', + timeA = ']', timeB = '[' + timeA, + timeToken = timeTemplate; - if (dateWithTime) { - var timeMeta = input.match(/^.{6,}?([,\s]+)(\d{1,2}).(?:\d{2,2})(?:.(\d{2,2}))?(?:\s([ap]m))?$/im); - if (null != timeMeta) { - dtSeparator = (! /undefined/i.test(typeof(timeMeta[1])) ? timeMeta[1] : dtSeparator); - // adjust timeToken to num digits of input hours - timeToken = (! /undefined/i.test(typeof(timeMeta[2])) && 1 == timeMeta[2].length ? timeToken.replace(/hh/ig, 'h') : timeToken); - // adjust timeToken to use seconds if input has them - timeToken = (! /undefined/i.test(typeof(timeMeta[3])) && 2 == timeMeta[3].length ? timeToken : timeToken.replace(/.ss/, '')); - // adjust timeToken to am/pm or AM/PM if input has it - timeToken = (! /undefined/i.test(typeof(timeMeta[4])) && 2 == timeMeta[4].length ? timeToken.replace(/A$/, (/[ap]m/.test(timeMeta[4]) ? 'a' : 'A')) : timeToken); - } - timeA = '
' + dtGlue + ']' + timeToken + '[' + timeA; - timeB = '[' + dtGlue + ']' + timeToken + timeB; - } + if (dateWithTime) { + var timeMeta = input.match(/([,\s]+)(\d{1,2})(?:(.)(\d\d)(?:(.)(\d\d))?)?(?:\s?([ap]m))?$/im); + if (null != timeMeta) { + dtSeparator = (! /undefined/i.test(typeof(timeMeta[1])) ? timeMeta[1] : dtSeparator); + // adjust timeToken to num digits of input hours + timeToken = (! /undefined/i.test(typeof(timeMeta[2])) && 1 == timeMeta[2].length ? timeToken.replace(/hh/ig, 'h') : timeToken); + // adjust timeToken to remove min if input has one and there is a pm + timeToken = (trimZero && ! /undefined/i.test(typeof(timeMeta[7])) + && (/undefined/i.test(typeof(timeMeta[4])) + || '00' == timeMeta[4]) ? timeToken.replace(/.mm/ig, '') : timeToken); + // adjust timeToken to use seconds if input has them + timeToken = (! /undefined/i.test(typeof(timeMeta[5])) && 2 == timeMeta[5].length ? timeToken : timeToken.replace(/.ss/, '')); + // adjust timeToken to am/pm or AM/PM if input has it + timeToken = (! /undefined/i.test(typeof(timeMeta[7])) && 2 == timeMeta[7].length ? timeToken.replace(/A$/, (/[ap]m/.test(timeMeta[7]) ? 'a' : 'A')) : timeToken); + } - var inputTokens = dateToken + dtSeparator + (dateWithTime ? timeToken : 'HH:mm:ss'); + var token_build = (/h+/i.test(timeToken) ? timeToken.replace(/^(h+).*/i, '[]$1[]') : ''); + if (/m+/i.test(timeToken)) { + token_build += (! /undefined/i.test(typeof(timeMeta[3])) ? '[]' + timeMeta[3] + '[]' : '') + + (! /undefined/i.test(typeof(timeMeta[4])) ? timeToken.replace(/.*?(m+).*/i, '[]$1[]') : ''); + if (/s+/i.test(timeToken)) { + token_build += (! /undefined/i.test(typeof(timeMeta[5])) ? '[]' + timeMeta[5] + '[]' : '') + + (! /undefined/i.test(typeof(timeMeta[6])) ? timeToken.replace(/.*?(s+).*/i, '[]$1[]') : ''); + } + } + timeToken = token_build + (! /undefined/i.test(typeof(timeMeta[7])) ? timeToken.replace(/.*?[\s0-9](a).*/i, '[]$1[]') : ''); - if (! moment(input + (dateWithTime ? '' : dtSeparator + '00:00:00'), inputTokens).isValid()) - return; + timeA = '' + dtGlue + ']' + timeToken + '[' + timeA; + timeB = '[' + dtGlue + ']' + timeToken + timeB; + } - moment.lang('en', { - calendar: { - lastDay:dateA + 'Yesterday' + timeA, sameDay:dateA + 'Today' + timeA, nextDay:dateA + 'Tomorrow' + timeA, - lastWeek:dateA + 'last] ddd' + timeB, nextWeek:dateA + 'on] ddd' + timeB, - sameElse:dateA + ']ddd, MMM D YYYY[' + timeA - }, - relativeTime: { - future:'in %s', past:'%s ago', s:'seconds', m:'a minute', mm:'%d minutes', h:'an hour', hh:'%d hours', - d:'a day', dd:'%d days', M:'a month', MM:'%d months', y:'a year', yy:'%d years' - } - }); + var inputTokens = dateTemplate + dtSeparator + (dateWithTime ? timeToken : 'HH:mm:ss'); - var airdatetime = moment(input + (dateWithTime ? '' : dtSeparator + '00:00:00'), inputTokens), - airdate = airdatetime.clone().hour(0).minute(0).second(0).millisecond(0), - today = moment({}), - day = Math.abs(airdate.diff(today, 'days')), - week = Math.abs(weekdiff = airdate.diff(today, 'week')), isPast = weekdiff < 0, - titleThis = false, qTipTime = false, - result = (0 == week ? airdatetime.calendar() : ''); + if (! moment(input + (dateWithTime ? '' : dtSeparator + '00:00:00'), inputTokens).isValid()) + return; - if (/\bOn\b/i.test(result)) { - var fuzzer = false, weekday = today.day(); - if (3 == weekday) - fuzzer = (5 <= day); - else if (4 == weekday || 5 == weekday) - fuzzer = (4 <= day); - else - fuzzer = (6 == day); - if (fuzzer) - result = result.replace(/\bOn\b/i, 'Next'); + moment.lang('en', { + calendar: { + lastDay:dateA + 'Yesterday' + timeA, sameDay:dateA + 'Today' + timeA, nextDay:dateA + 'Tomorrow' + timeA, + lastWeek:dateA + 'last] ddd' + timeB, nextWeek:dateA + 'on] ddd' + timeB, + sameElse:dateA + ']ddd, MMM D YYYY[' + timeA + }, + relativeTime: { + future:'in %s', past:'%s ago', s:'seconds', m:'a minute', mm:'%d minutes', h:'an hour', hh:'%d hours', + d:'a day', dd:'%d days', M:'a month', MM:'%d months', y:'a year', yy:'%d years' + } + }); - } else if (! /\b((yester|to)day\b|tomo|last\b)/i.test(result)) { - if (14 > day) - result = airdate.from(today) + (dateWithTime ? dtGlue + airdatetime.format(timeToken) : ''); - else if (4 > week) { - result = (isPast ? '' : 'in ') + (1 == week ? 'a' : week) + ' week' + (1 == week ? '' : 's') + (isPast ? ' ago' : ''); - qTipTime = true; - } else { - result = airdate.from(today); - qTipTime = true; - var month = airdate.diff(today, 'month'); - if (1 == parseInt(airdate.year() - today.year())) - result += (dtInline ? ' ' : '
') + '(Next Year)'; - } - titleThis = true; - } + var airdatetime = moment(input + (dateWithTime ? '' : dtSeparator + '00:00:00'), inputTokens), + airdate = airdatetime.clone().hour(0).minute(0).second(0).millisecond(0), + today = moment({}), + day = Math.abs(airdate.diff(today, 'days')), + week = Math.abs(weekdiff = airdate.diff(today, 'week')), isPast = weekdiff < 0, + titleThis = false, qTipTime = false, + result = (0 == week ? airdatetime.calendar() : ''); - var n = false; // disable for prod - $(this).html(result); - if (dateWithTime && /(yester|to)day/i.test(result)) - $(this).find('.fd').attr('title',(n?'1) ':'') + moment.duration(airdatetime.diff(moment(),'seconds'),'seconds').humanize(true)).each(addQTip); - else if (dateWithTime) - $(this).find('.fd').attr('title',(n?'2) ':'') + airdate.from(today)).each(addQTip); - else if (! /today/i.test(result)) - $(this).find('.fd').attr('title',(n?'3) ':'') + airdate.from(today)).each(addQTip); - else - titleThis = false; + if (/\bOn\b/i.test(result)) { + var fuzzer = false, weekday = today.day(); + if (3 == weekday) + fuzzer = (5 <= day); + else if (4 == weekday || 5 == weekday) + fuzzer = (4 <= day); + else + fuzzer = (6 == day); + if (fuzzer) + result = result.replace(/\bOn\b/i, 'Next'); - if (titleThis) - if (dateWithTime && qTipTime) - $(this).attr('title',(n?'4) ':'') + airdatetime.format(inputTokens)).each(addQTip); - else - $(this).attr('title',(n?'5) ':'') + airdate.format(dateToken)).each(addQTip); - else - if (dateWithTime && qTipTime) - $(this).find('.ft').attr('title',(n?'6) ':'') + airdatetime.format(inputTokens)).each(addQTip); - else - $(this).find('.ft').attr('title',(n?'7) ':'') + airdate.format(dateToken)).each(addQTip); - }); + } else if (! /\b((yester|to)day\b|tomo|last\b)/i.test(result)) { + if (14 > day) + result = airdate.from(today) + (dateWithTime ? dtGlue + airdatetime.format(timeToken) : ''); + else if (4 > week) { + result = (isPast ? '' : 'in ') + (1 == week ? 'a' : week) + ' week' + (1 == week ? '' : 's') + (isPast ? ' ago' : ''); + qTipTime = true; + } else { + result = airdate.from(today); + qTipTime = true; + var month = airdate.diff(today, 'month'); + if (1 == parseInt(airdate.year() - today.year())) + result += (dtInline ? ' ' : '
') + '(Next Year)'; + } + titleThis = true; + } + + var n = false; // disable for prod + $(this).html(result); + if (dateWithTime && /(yester|to)day/i.test(result)) + $(this).find('.fd').attr('title',(n?'1) ':'') + moment.duration(airdatetime.diff(moment(),'seconds'),'seconds').humanize(true)).each(addQTip); + else if (dateWithTime) + $(this).find('.fd').attr('title',(n?'2) ':'') + airdate.from(today)).each(addQTip); + else if (! /today/i.test(result)) + $(this).find('.fd').attr('title',(n?'3) ':'') + airdate.from(today)).each(addQTip); + else + titleThis = false; + + if (titleThis) + if (dateWithTime && qTipTime) + $(this).attr('title',(n?'4) ':'') + airdatetime.format(inputTokens)).each(addQTip); + else + $(this).attr('title',(n?'5) ':'') + airdate.format(dateTemplate)).each(addQTip); + else + if (dateWithTime && qTipTime) + $(this).find('.ft').attr('title',(n?'6) ':'') + airdatetime.format(inputTokens)).each(addQTip); + else + $(this).find('.ft').attr('title',(n?'7) ':'') + airdate.format(dateTemplate)).each(addQTip); + }); } diff --git a/sickbeard/sbdatetime.py b/sickbeard/sbdatetime.py index 5e96f667..9f49b865 100644 --- a/sickbeard/sbdatetime.py +++ b/sickbeard/sbdatetime.py @@ -19,6 +19,7 @@ import datetime import locale import functools +import re import sickbeard from sickbeard.network_timezones import sb_timezone @@ -82,12 +83,12 @@ date_presets = ('%Y-%m-%d', '%A, %b %d, %Y', '%B %d, %Y', '%a, %B %d, %Y', - '%A, %B %d, %Y' -) + '%A, %B %d, %Y') time_presets = ('%I:%M:%S %p', - '%H:%M:%S' -) + '%I:%M:%S %P', + '%H:%M:%S') + # helper class class static_or_instance(object): @@ -104,142 +105,98 @@ class sbdatetime(datetime.datetime): @static_or_instance def convert_to_setting(self, dt=None): + obj = (dt, self)[self is not None] try: - if sickbeard.TIMEZONE_DISPLAY == 'local': - if self is None: - return dt.astimezone(sb_timezone) - else: - return self.astimezone(sb_timezone) - else: - if self is None: - return dt - else: - return self + if 'local' == sickbeard.TIMEZONE_DISPLAY: + return obj.astimezone(sb_timezone) except: - if self is None: - return dt - else: - return self + pass + + return obj + + @static_or_instance + def setlocale(self, setlocale=True, use_has_locale=None, locale_str=''): + if setlocale: + try: + if None is use_has_locale or use_has_locale: + locale.setlocale(locale.LC_TIME, locale_str) + except: + if None is not use_has_locale: + sbdatetime.has_locale = False + pass # display Time in SickGear Format @static_or_instance - def sbftime(self, dt=None, show_seconds=False, t_preset=None): + def sbftime(self, dt=None, show_seconds=False, t_preset=None, setlocale=True, markup=False): - try:locale.setlocale(locale.LC_TIME, '') - except:pass - - try: - if sbdatetime.has_locale: - locale.setlocale(locale.LC_TIME, 'us_US') - except: - sbdatetime.has_locale = False + sbdatetime.setlocale(setlocale=setlocale, use_has_locale=sbdatetime.has_locale, locale_str='us_US') strt = '' try: - if self is None: - if dt is not None: - if t_preset is not None: - strt = dt.strftime(t_preset) - elif show_seconds: - strt = dt.strftime(sickbeard.TIME_PRESET_W_SECONDS) - else: - strt = dt.strftime(sickbeard.TIME_PRESET) - else: - if t_preset is not None: - strt = self.strftime(t_preset) - elif show_seconds: - strt = self.strftime(sickbeard.TIME_PRESET_W_SECONDS) - else: - strt = self.strftime(sickbeard.TIME_PRESET) - finally: - try: - if sbdatetime.has_locale: - locale.setlocale(locale.LC_TIME, '') - except: - sbdatetime.has_locale = False + obj = (dt, self)[self is not None] + if None is not obj: + tmpl = (((sickbeard.TIME_PRESET, sickbeard.TIME_PRESET_W_SECONDS)[show_seconds]), + t_preset)[None is not t_preset] + tmpl = (tmpl.replace(':%S', ''), tmpl)[show_seconds] + strt = obj.strftime(tmpl.replace('%P', '%p')) + + if sickbeard.TRIM_ZERO: + strt = re.sub(r'^0(\d:\d\d)', r'\1', strt) + + if re.search(r'(?im)%p$', tmpl): + if '%p' in tmpl: + strt = strt.upper() + elif '%P' in tmpl: + strt = strt.lower() + + if sickbeard.TRIM_ZERO: + strt = re.sub(r'(?im)^(\d+)(?::00)?(\s?[ap]m)', r'\1\2', strt) + + if markup: + match = re.search(r'(?im)(\d{1,2})(?:(.)(\d\d)(?:(.)(\d\d))?)?(?:\s?([ap]m))?$', strt) + if match: + strt = ('%s%s%s%s%s%s' % ( + ('%s' % match.group(1), '')[None is match.group(1)], + ('%s' % match.group(2), '')[None is match.group(2)], + ('%s' % match.group(3), '')[None is match.group(3)], + ('%s' % match.group(4), '')[None is match.group(4)], + ('%s' % match.group(5), '')[None is match.group(5)], + ('%s' % match.group(6), '')[None is match.group(6)])) + + finally: + sbdatetime.setlocale(setlocale=setlocale, use_has_locale=sbdatetime.has_locale) return strt # display Date in SickGear Format @static_or_instance - def sbfdate(self, dt=None, d_preset=None): + def sbfdate(self, dt=None, d_preset=None, setlocale=True): - try: - locale.setlocale(locale.LC_TIME, '') - except: - pass + sbdatetime.setlocale(setlocale=setlocale) strd = '' try: - if self is None: - if dt is not None: - if d_preset is not None: - strd = dt.strftime(d_preset) - else: - strd = dt.strftime(sickbeard.DATE_PRESET) - else: - if d_preset is not None: - strd = self.strftime(d_preset) - else: - strd = self.strftime(sickbeard.DATE_PRESET) + obj = (dt, self)[self is not None] + if None is not obj: + strd = obj.strftime((sickbeard.DATE_PRESET, d_preset)[None is not d_preset]) + finally: - - try: - locale.setlocale(locale.LC_TIME, '') - except: - pass - + sbdatetime.setlocale(setlocale=setlocale) return strd # display Datetime in SickGear Format @static_or_instance - def sbfdatetime(self, dt=None, show_seconds=False, d_preset=None, t_preset=None): + def sbfdatetime(self, dt=None, show_seconds=False, d_preset=None, t_preset=None, markup=False): - try: - locale.setlocale(locale.LC_TIME, '') - except: - pass + sbdatetime.setlocale() strd = '' + obj = (dt, self)[self is not None] try: - if self is None: - if dt is not None: - if d_preset is not None: - strd = dt.strftime(d_preset) - else: - strd = dt.strftime(sickbeard.DATE_PRESET) - try: - if sbdatetime.has_locale: - locale.setlocale(locale.LC_TIME, 'us_US') - except: - sbdatetime.has_locale = False - if t_preset is not None: - strd += u', ' + dt.strftime(t_preset) - elif show_seconds: - strd += u', ' + dt.strftime(sickbeard.TIME_PRESET_W_SECONDS) - else: - strd += u', ' + dt.strftime(sickbeard.TIME_PRESET) - else: - if d_preset is not None: - strd = self.strftime(d_preset) - else: - strd = self.strftime(sickbeard.DATE_PRESET) - try: - if sbdatetime.has_locale: - locale.setlocale(locale.LC_TIME, 'us_US') - except: - sbdatetime.has_locale = False - if t_preset is not None: - strd += u', ' + self.strftime(t_preset) - elif show_seconds: - strd += u', ' + self.strftime(sickbeard.TIME_PRESET_W_SECONDS) - else: - strd += u', ' + self.strftime(sickbeard.TIME_PRESET) - finally: - try: - if sbdatetime.has_locale: - locale.setlocale(locale.LC_TIME, '') - except: - sbdatetime.has_locale = False + if None is not obj: + strd = u'%s, %s' % (obj.strftime((sickbeard.DATE_PRESET, d_preset)[None is not d_preset]), + sbdatetime.sbftime(dt, show_seconds, t_preset, False, markup)) + finally: + sbdatetime.setlocale(use_has_locale=sbdatetime.has_locale) return strd