# HG changeset patch # User Adam Chlipala # Date 1322152071 18000 # Node ID c6cc104a47ac0f3f2e785859ee75bd6224f0c3be # Parent 77180224f1f9830a1cacbdb4e91b8ed9d2e41102 Client-side timef diff -r 77180224f1f9 -r c6cc104a47ac lib/js/urweb.js --- a/lib/js/urweb.js Thu Nov 24 11:09:50 2011 -0500 +++ b/lib/js/urweb.js Thu Nov 24 11:27:51 2011 -0500 @@ -157,6 +157,206 @@ } } +/* + strftime for Javascript + Copyright (c) 2008, Philip S Tellis + All rights reserved. + + This code is distributed under the terms of the BSD licence + + Redistribution and use of this software in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions + and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + * The names of the contributors to this file may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +Date.ext = {}; +Date.ext.util = {}; +Date.ext.util.xPad=function(x, pad, r) +{ + if(typeof(r) == 'undefined') + { + r=10; + } + for( ; parseInt(x, 10)1; r/=10) + x = pad.toString() + x; + return x.toString(); +}; +Date.prototype.locale = 'en-US'; +if(document.getElementsByTagName('html') && document.getElementsByTagName('html')[0].lang) +{ + Date.prototype.locale = document.getElementsByTagName('html')[0].lang; +} +Date.ext.locales = { }; +Date.ext.locales.en = { + a: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + A: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + b: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + B: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + c: '%a %d %b %Y %T %Z', + p: ['AM', 'PM'], + P: ['am', 'pm'], + x: '%d/%m/%y', + X: '%T' +}; +Date.ext.locales['en-US'] = Date.ext.locales.en; +Date.ext.locales['en-US'].c = '%a %d %b %Y %r %Z'; +Date.ext.locales['en-US'].x = '%D'; +Date.ext.locales['en-US'].X = '%r'; +Date.ext.locales['en-GB'] = Date.ext.locales.en; +Date.ext.locales['en-AU'] = Date.ext.locales['en-GB']; +Date.ext.formats = { + a: function(d) { return Date.ext.locales[d.locale].a[d.getDay()]; }, + A: function(d) { return Date.ext.locales[d.locale].A[d.getDay()]; }, + b: function(d) { return Date.ext.locales[d.locale].b[d.getMonth()]; }, + B: function(d) { return Date.ext.locales[d.locale].B[d.getMonth()]; }, + c: 'toLocaleString', + C: function(d) { return Date.ext.util.xPad(parseInt(d.getFullYear()/100, 10), 0); }, + d: ['getDate', '0'], + e: ['getDate', ' '], + g: function(d) { return Date.ext.util.xPad(parseInt(Date.ext.util.G(d)/100, 10), 0); }, + G: function(d) { + var y = d.getFullYear(); + var V = parseInt(Date.ext.formats.V(d), 10); + var W = parseInt(Date.ext.formats.W(d), 10); + + if(W > V) { + y++; + } else if(W===0 && V>=52) { + y--; + } + + return y; + }, + H: ['getHours', '0'], + I: function(d) { var I=d.getHours()%12; return Date.ext.util.xPad(I===0?12:I, 0); }, + j: function(d) { + var ms = d - new Date('' + d.getFullYear() + '/1/1 GMT'); + ms += d.getTimezoneOffset()*60000; + var doy = parseInt(ms/60000/60/24, 10)+1; + return Date.ext.util.xPad(doy, 0, 100); + }, + m: function(d) { return Date.ext.util.xPad(d.getMonth()+1, 0); }, + M: ['getMinutes', '0'], + p: function(d) { return Date.ext.locales[d.locale].p[d.getHours() >= 12 ? 1 : 0 ]; }, + P: function(d) { return Date.ext.locales[d.locale].P[d.getHours() >= 12 ? 1 : 0 ]; }, + S: ['getSeconds', '0'], + u: function(d) { var dow = d.getDay(); return dow===0?7:dow; }, + U: function(d) { + var doy = parseInt(Date.ext.formats.j(d), 10); + var rdow = 6-d.getDay(); + var woy = parseInt((doy+rdow)/7, 10); + return Date.ext.util.xPad(woy, 0); + }, + V: function(d) { + var woy = parseInt(Date.ext.formats.W(d), 10); + var dow1_1 = (new Date('' + d.getFullYear() + '/1/1')).getDay(); + var idow = woy + (dow1_1 > 4 || dow1_1 <= 1 ? 0 : 1); + if(idow == 53 && (new Date('' + d.getFullYear() + '/12/31')).getDay() < 4) + { + idow = 1; + } + else if(idow === 0) + { + idow = Date.ext.formats.V(new Date('' + (d.getFullYear()-1) + '/12/31')); + } + + return Date.ext.util.xPad(idow, 0); + }, + w: 'getDay', + W: function(d) { + var doy = parseInt(Date.ext.formats.j(d), 10); + var rdow = 7-Date.ext.formats.u(d); + var woy = parseInt((doy+rdow)/7, 10); + return Date.ext.util.xPad(woy, 0, 10); + }, + y: function(d) { return Date.ext.util.xPad(d.getFullYear()%100, 0); }, + Y: 'getFullYear', + z: function(d) { + var o = d.getTimezoneOffset(); + var H = Date.ext.util.xPad(parseInt(Math.abs(o/60), 10), 0); + var M = Date.ext.util.xPad(o%60, 0); + return (o>0?'-':'+') + H + M; + }, + Z: function(d) { return d.toString().replace(/^.*\(([^)]+)\)$/, '$1'); }, + '%': function(d) { return '%'; } +}; +Date.ext.aggregates = { + c: 'locale', + D: '%m/%d/%y', + h: '%b', + n: '\n', + r: '%I:%M:%S %p', + R: '%H:%M', + t: '\t', + T: '%H:%M:%S', + x: 'locale', + X: 'locale' +}; +Date.ext.aggregates.z = Date.ext.formats.z(new Date()); +Date.ext.aggregates.Z = Date.ext.formats.Z(new Date()); +Date.ext.unsupported = { }; +function strftime(fmt, thisTime) +{ + var thisDate = new Date(); + thisDate.setTime(thisTime / 1000); + + if(!(thisDate.locale in Date.ext.locales)) + { + if(thisDate.locale.replace(/-[a-zA-Z]+$/, '') in Date.ext.locales) + { + thisDate.locale = thisDate.locale.replace(/-[a-zA-Z]+$/, ''); + } + else + { + thisDate.locale = 'en-US'; + } + } + + var d = thisDate; + while(fmt.match(/%[cDhnrRtTxXzZ]/)) + { + fmt = fmt.replace(/%([cDhnrRtTxXzZ])/g, function(m0, m1) + { + var f = Date.ext.aggregates[m1]; + return (f == 'locale' ? Date.ext.locales[d.locale][m1] : f); + }); + } + + var str = fmt.replace(/%([aAbBCdegGHIjmMpPSuUVwWyY%])/g, function(m0, m1) + { + var f = Date.ext.formats[m1]; + if(typeof(f) == 'string') { + return d[f](); + } else if(typeof(f) == 'function') { + return f.call(d, d); + } else if(typeof(f) == 'object' && typeof(f[0]) == 'string') { + return Date.ext.util.xPad(d[f[0]](), f[1]); + } else { + return m1; + } + }); + d=null; + return str; +}; + +// End of code from Philip S Tellis + // Error handling diff -r 77180224f1f9 -r c6cc104a47ac src/settings.sml --- a/src/settings.sml Thu Nov 24 11:09:50 2011 -0500 +++ b/src/settings.sml Thu Nov 24 11:27:51 2011 -0500 @@ -206,6 +206,7 @@ val jsFuncsBase = basisM [("alert", "alert"), ("stringToTime", "stringToTime"), ("stringToTime_error", "stringToTime_error"), + ("timef", "strftime"), ("confirm", "confrm"), ("get_client_source", "sg"), ("current", "scur"), diff -r 77180224f1f9 -r c6cc104a47ac tests/timef.ur --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/timef.ur Thu Nov 24 11:27:51 2011 -0500 @@ -0,0 +1,12 @@ +fun main () : transaction page = + date <- source ""; + format <- source ""; + return + + + + | Some d => {[timef f d]})}/> +