2010-01-20 16 views
7

A continuación se muestra un plugin muy agradable para jQuery, muy similar a lo que usan aquí en SO. El problema para mí es que usa esto para convertir el tiempo.jQuery Hace tiempo de una marca de tiempo?

<time class="timeago" datetime="2008-07-17T09:24:17Z">July 17, 2008</time> 

Eso sería genial, excepto que el tiempo del almacén en mi sitio en la marca de hora UTC y no como un tiempo de formateado, ¿hay una manera de convertir algo como esto para usar una marca de tiempo? Sé que en PHP podría convertir mi marca de tiempo a este formato, pero parece demasiado caro convertir muchas veces en 1 página en PHP. Podría estar equivocado, ¿alguien más hace esto en jquery pero a partir de una marca de tiempo real?

También actualmente hago esto en PHP en un sitio para mostrar "hace 2 horas 4 minutos" pero ¿sería mejor usar javascript para esto en lugar de PHP?

/* 
* timeago: a jQuery plugin, version: 0.8.1 (2010-01-04) 
* @requires jQuery v1.2.3 or later 
* 
* Timeago is a jQuery plugin that makes it easy to support automatically 
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). 
* 
* For usage and examples, visit: 
* http://timeago.yarp.com/ 
* Copyright (c) 2008-2010, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org) 
*/ 
(function($) { 
    $.timeago = function(timestamp) { 
    if (timestamp instanceof Date) return inWords(timestamp); 
    else if (typeof timestamp == "string") return inWords($.timeago.parse(timestamp)); 
    else return inWords($.timeago.datetime(timestamp)); 
    }; 
    var $t = $.timeago; 

    $.extend($.timeago, { 
    settings: { 
     refreshMillis: 60000, 
     allowFuture: false, 
     strings: { 
     prefixAgo: null, 
     prefixFromNow: null, 
     suffixAgo: "ago", 
     suffixFromNow: "from now", 
     ago: null, // DEPRECATED, use suffixAgo 
     fromNow: null, // DEPRECATED, use suffixFromNow 
     seconds: "less than a minute", 
     minute: "about a minute", 
     minutes: "%d minutes", 
     hour: "about an hour", 
     hours: "about %d hours", 
     day: "a day", 
     days: "%d days", 
     month: "about a month", 
     months: "%d months", 
     year: "about a year", 
     years: "%d years" 
     } 
    }, 
    inWords: function(distanceMillis) { 
     var $l = this.settings.strings; 
     var prefix = $l.prefixAgo; 
     var suffix = $l.suffixAgo || $l.ago; 
     if (this.settings.allowFuture) { 
     if (distanceMillis < 0) { 
      prefix = $l.prefixFromNow; 
      suffix = $l.suffixFromNow || $l.fromNow; 
     } 
     distanceMillis = Math.abs(distanceMillis); 
     } 

     var seconds = distanceMillis/1000; 
     var minutes = seconds/60; 
     var hours = minutes/60; 
     var days = hours/24; 
     var years = days/365; 

     var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || 
     seconds < 90 && substitute($l.minute, 1) || 
     minutes < 45 && substitute($l.minutes, Math.round(minutes)) || 
     minutes < 90 && substitute($l.hour, 1) || 
     hours < 24 && substitute($l.hours, Math.round(hours)) || 
     hours < 48 && substitute($l.day, 1) || 
     days < 30 && substitute($l.days, Math.floor(days)) || 
     days < 60 && substitute($l.month, 1) || 
     days < 365 && substitute($l.months, Math.floor(days/30)) || 
     years < 2 && substitute($l.year, 1) || 
     substitute($l.years, Math.floor(years)); 

     return $.trim([prefix, words, suffix].join(" ")); 
    }, 
    parse: function(iso8601) { 
     var s = $.trim(iso8601); 
     s = s.replace(/-/,"/").replace(/-/,"/"); 
     s = s.replace(/T/," ").replace(/Z/," UTC"); 
     s = s.replace(/([\+-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 
     return new Date(s); 
    }, 
    datetime: function(elem) { 
     // jQuery's `is()` doesn't play well with HTML5 in IE 
     var isTime = $(elem).get(0).tagName.toLowerCase() == 'time'; // $(elem).is('time'); 
     var iso8601 = isTime ? $(elem).attr('datetime') : $(elem).attr('title'); 
     return $t.parse(iso8601); 
    } 
    }); 

    $.fn.timeago = function() { 
    var self = this; 
    self.each(refresh); 

    var $s = $t.settings; 
    if ($s.refreshMillis > 0) { 
     setInterval(function() { self.each(refresh); }, $s.refreshMillis); 
    } 
    return self; 
    }; 

    function refresh() { 
    var data = prepareData(this); 
    if (!isNaN(data.datetime)) { 
     $(this).text(inWords(data.datetime)); 
    } 
    return this; 
    } 

    function prepareData(element) { 
    element = $(element); 
    if (element.data("timeago") === undefined) { 
     element.data("timeago", { datetime: $t.datetime(element) }); 
     var text = $.trim(element.text()); 
     if (text.length > 0) element.attr("title", text); 
    } 
    return element.data("timeago"); 
    } 

    function inWords(date) { 
    return $t.inWords(distance(date)); 
    } 

    function distance(date) { 
    return (new Date().getTime() - date.getTime()); 
    } 

    function substitute(stringOrFunction, value) { 
    var string = $.isFunction(stringOrFunction) ? stringOrFunction(value) : stringOrFunction; 
    return string.replace(/%d/i, value); 
    } 

    // fix for IE6 suckage 
    document.createElement('abbr'); 
    document.createElement('time'); 
})(jQuery); 

Respuesta

8

Tuve el mismo problema. Estoy utilizando marcas de tiempo de Unix que se generan a partir de PHP, así que decidí hacer un hack rápido y extender la función de análisis de jQuery timeago para manejar marcas de tiempo adicionalmente. Funciona de maravilla. Simplemente busque la función Parse en la línea 79 en el archivo jquery.timeago.js y reemplácela con la siguiente:

parse: function(iso8601) { 
    if ((iso8601 - 0) == iso8601 && iso8601.length > 0) { // Checks if iso8601 is a unix timestamp 
    var s = new Date(iso8601); 
    if (isNaN(s.getTime())) { // Checks if iso8601 is formatted in milliseconds 
     var s = new Date(iso8601 * 1000); //if not, add milliseconds 
    } 
    return s; 
    } 

    var s = $.trim(iso8601); 
    s = s.replace(/-/,"/").replace(/-/,"/"); 
    s = s.replace(/T/," ").replace(/Z/," UTC"); 
    s = s.replace(/([\+-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 
    return new Date(s); 
}, 
+0

Exactamente lo que estaba buscando gracias. –

+0

Esto es increíble, exactamente lo que quería hacer. ¡Gracias por compartir! –

+0

+1 ¡Esta debería ser más votada que la otra respuesta! –

-1

Sería mejor utilizar ambos, pero no es necesario hacerlo dinámico con JS.

De hecho, solo he visto este comportamiento en Facebook.

Además, ¿sabe que la etiqueta <time> es HTML5? Puede crear algunas incompatibilidades.

+0

¿Hay alguna manera de actualizarlo automáticamente? – Antonio

2

Me gusta usar DateJS.com que es una biblioteca javascript de fecha y hora. Usted puede hacer cosas interesantes como esta (pantalla hace 2 horas en un <span id='myfield'></span>):

$('#myfield').text((2).hours().ago().toString("HH:mm")); 
+0

Por el amor de Dios, necesita poder usar "marcas de tiempo Unix", el tiempo ya es suficiente y es mejor que date.js si desea usar fechas. –

3

Aquí hay algo en JavaScript usando nada más que las marcas de tiempo de Unix.

var d1; 
var d2; 
d1 = (new Date()).getTime(); setTimeout(function() { d2 = (new Date()).getTime(); }, 5000); 
var secondsElapsed = (d2 - d1)/1000; 
secondsElapsed; // 5 seconds 

Ahora, puede almacenar una marca de tiempo en una variable de JavaScript en el mismo alcance que su función "timeago", o su puede almacenar en un elemento HTML. Como se mencionó, el elemento time es un elemento HTML 5. Se podría hacer algo como:


<p class="timestamp" style="display: none;">123456</p> 

Entonces tal vez usted tiene un artículo comentario como:


<div class="comment"> 
    <p>Lorem ipsum et dolor...</p> 
    <p class="timestamp" style="display: none;">123456</p> 
</div> 

A continuación, podría obtener la marca de tiempo para un comentario de (suponiendo jQuery ya que ha mencionado es):


var tstamps = $('.comment .timestamp'); // array of comment timestamps 
var timeago = ((new Date()).getTime() - tstamps[0].html())/1000; 

Es un poco hackish, pero funcionaría (si lo hice bien).

Cuestiones relacionadas