2011-05-03 3 views
4

Le résultat de datediff(ss, '01/01/1970', '12/31/2050') est un bigint alors datediff déborde.Comment prendre en charge bigint dans datetime

Comment puis-je obtenir à partir d'une valeur bigint à sa date équivalente et de retour si la date maximale peut être en SQL est int?

Je dois être en mesure de stocker nombre de secondes entre 01/01/1970 et 12/31/2050 dans SQL (que je fais en tant char) mais convertir cette valeur à sa date de calendrier pour l'affichage dans une page Web.

Toutes les idées seraient appréciées.

Merci!

+0

Tous linux/unix ont ce problème aussi bien. Il est bien connu que [l'époque débordera] (http://en.wikipedia.org/wiki/Unix_time#Representing_the_number) si elle n'est pas modifiée de 32bits. – Oded

Répondre

2

Vous pouvez diffuser des datetimes sous la forme de nombres flottants correspondant au nombre de jours écoulés depuis 1900-01-01 00:00:00. Les parties inférieures à jours sont alors simplement les fractions. Substracting ces chiffres et mise à l'échelle par secondes dans une journée devrait faire.

DECLARE @ d1 DATETIME

DECLARE @ d2 DATETIME

SELECT @ d1 = '01/01/1970'

SELECT @ d2 = '12/31/2050

SELECT (CAST (@ d2 COMME FLOTTANT) - CAST (@ d1 AS FLOAT)) * 3600 * 24

Mais vous serez probablement capable de trouver de meilleures solutions;)

+0

Decimal pourrait être plus rapide je me demande? – Rbjz

2
CREATE FUNCTION dbo.SecondsSince1970(@date datetime) 
RETURNS bigint 
AS 
BEGIN 
    RETURN 
     CASE WHEN @date > '2038-01-19' 
      THEN CAST(DATEDIFF(ss, '2038-01-19', @date) AS bigint) 
       + DATEDIFF(ss, '1970-01-01', '2038-01-19') 
      ELSE DATEDIFF(ss, '1970-01-01', @date) 
     END 
END 
4

Ceci vous donnera des milisecondes. Facile à adapter à quelques secondes ...

declare @dfrom datetime = '1970-01-01 16:15:33.021' 
declare @dto datetime = '2058-01-01 15:00:55.557' 

declare @diff bigint = 
    cast(DATEDIFF(d, @dfrom, @dto) as bigint) * 24 * 3600 * 1000 
    + DATEDIFF(ms, cast(@dfrom as time), cast(@dto as time))  

declare @dreverse datetime = 
    dateadd(ms, @diff % (1000 * 3600 * 24), 
     dateadd(day, @diff/(1000 * 3600 * 24), @dfrom)) 

select @dfrom as [From], @dto as [To], @diff as [Diff], @dreverse as [Reverse] for xml path('') 

donne:

<From>1970-01-01T16:15:33.020</From> 
<To>2058-01-01T15:00:55.557</To> 
<Diff>2777064322537</Diff> 
<Reverse>2058-01-01T15:00:55.557</Reverse> 
+1

Ce n'est pas une bonne idée, sauf si vous êtes heureux d'ignorer les heures et les secondes le premier et le dernier jour. Datediff compte les "limites". Si vous sélectionnez le fichier datediff (d, '2013-01-01 04:00:00', '2013-01-02 10:00:00'), le résultat est 1 (jour), pas 1.25 jours, car le type de retour est entier. – Davos

+1

Davos, c'est exactement pourquoi il y a la partie ms en deuxième ligne ...? – Rbjz

+0

Hmm J'ai manqué cela, mais il y a toujours un problème si après avoir lancé comme le temps que votre temps De pourrait être plus tard dans la journée que votre temps TO, de sorte que vous ajoutez des millisecondes négatives. Peut-être soustraire des millisecondes d'une journée complète si elle est négative – Davos

Questions connexes