Je ne sais pas si cela devrait être une question distincte, mais comment convertir entre une date et une heure?
Andrew Grimm
8
Les réponses acceptées et les mieux notées ne sont plus les plus précises sous les versions modernes de Ruby. Voir les réponses de @theTinMan et de @PatrickMcKenzie ci-dessous.
Phrogz
Réponses:
50
Vous aurez besoin de deux conversions légèrement différentes.
Pour convertir de Time en, DateTimevous pouvez modifier la classe Time comme suit:
require 'date'classTimedef to_datetime
# Convert seconds + microseconds into a fractional number of seconds
seconds = sec +Rational(usec,10**6)# Convert a UTC offset measured in minutes to one measured in a# fraction of a day.
offset =Rational(utc_offset,60*60*24)DateTime.new(year, month, day, hour, min, seconds, offset)endend
Des ajustements similaires à Date vous permettront de convertir DateTime en Time .
classDatedef to_gm_time
to_time(new_offset,:gm)enddef to_local_time
to_time(new_offset(DateTime.now.offset-offset),:local)end
private
def to_time(dest, method)#Convert a fraction of a day to a number of microseconds
usec =(dest.sec_fraction *60*60*24*(10**6)).to_i
Time.send(method, dest.year, dest.month, dest.day, dest.hour, dest.min,
dest.sec, usec)endend
Notez que vous devez choisir entre l'heure locale et l'heure GM / UTC.
Les deux extraits de code ci-dessus sont tirés de O'Reilly's Ruby Cookbook . Leur politique de réutilisation du code le permet.
Cela s'arrêtera le 1.9 où DateTime # sec_fraction renvoie le nombre de millisecondes dans une seconde. Pour la version 1.9, vous voulez utiliser: usec = dest.sec_fraction * 10 ** 6
dkubb
185
require 'time'
require 'date'
t =Time.now
d =DateTime.now
dd =DateTime.parse(t.to_s)
tt =Time.parse(d.to_s)
+1 Ce n'est peut-être pas le plus efficace en exécution, mais cela fonctionne, c'est concis et c'est très lisible.
Walt Jones
6
Malheureusement, cela ne fonctionne vraiment que lorsqu'il s'agit de l'heure locale. Si vous commencez avec une date / heure ou une heure avec un fuseau horaire différent, la fonction d'analyse sera convertie en fuseau horaire local. Vous perdez essentiellement le fuseau horaire d'origine.
Bernard
6
Depuis ruby 1.9.1, DateTime.parse conserve le fuseau horaire. (Je n'ai pas accès aux versions antérieures.) Time.parse ne conserve pas le fuseau horaire, car il représente le time_t standard POSIX, qui, je crois, est une différence entière par rapport à l'époque. Toute conversion en temps doit avoir le même comportement.
anshul
1
Vous avez raison. DateTime.parse fonctionne dans 1.9.1 mais pas Time.parse. Dans tous les cas, il est moins sujet aux erreurs (cohérent) et probablement plus rapide à utiliser DateTime.new (...) et Time.new (..). Voir ma réponse pour un exemple de code.
Bernard
1
Salut @anshul. Je ne veux pas dire que je dis :-). Les informations de fuseau horaire ne sont pas conservées lors de l'utilisation de Time.parse (). C'est facile à tester. Dans votre code ci-dessus, remplacez simplement d = DateTime.now par d = DateTime.new (2010,01,01, 10,00,00, Rational (-2, 24)). tt affichera maintenant la date d convertie dans votre fuseau horaire local. Vous pouvez toujours faire de l'arithmétique de date et tout sauf les informations tz originales sont perdues. Cette information est un contexte pour la date et elle est souvent importante. Voir ici: stackoverflow.com/questions/279769/…
Bernard
63
En tant que mise à jour de l'état de l'écosystème Ruby Date, DateTimeet Timeont maintenant des méthodes pour convertir entre les différentes classes. Utilisation de Ruby 1.9.2+:
Oups. Je viens de réaliser que c'est un problème Ruby on Rails et non un problème Ruby: stackoverflow.com/questions/11277454/… . Ils ont même déposé un bogue contre cette méthode dans la ligne 2.x et l'ont marqué «ne résoudra pas». Horrible décision à mon humble avis. Le comportement Rails rompt totalement l'interface Ruby sous-jacente.
Jesse Clark
12
Malheureusement, le DateTime.to_time, Time.to_datetimeetTime.parse fonctions ne conservent pas les informations de fuseau horaire. Tout est converti en fuseau horaire local lors de la conversion. L'arithmétique des dates fonctionne toujours, mais vous ne pourrez pas afficher les dates avec leurs fuseaux horaires d'origine. Ces informations contextuelles sont souvent importantes. Par exemple, si je souhaite voir les transactions effectuées pendant les heures de bureau à New York, je préfère probablement les voir affichées dans leur fuseau horaire d'origine, pas dans mon fuseau horaire local en Australie (qui est 12 heures avant New York).
Les méthodes de conversion ci-dessous conservent ces informations tz.
Pour Ruby 1.8, regardez la réponse de Gordon Wilson . Il provient du bon vieux livre de recettes Ruby fiable.
Pour Ruby 1.9, c'est un peu plus facile.
require 'date'# Create a date in some foreign time zone (middle of the Atlantic)
d =DateTime.new(2010,01,01,10,00,00,Rational(-2,24))
puts d
# Convert DateTime to Time, keeping the original timezone
t =Time.new(d.year, d.month, d.day, d.hour, d.min, d.sec, d.zone)
puts t
# Convert Time to DateTime, keeping the original timezone
d =DateTime.new(t.year, t.month, t.day, t.hour, t.min, t.sec,Rational(t.gmt_offset /3600,24))
puts d
Le temps est compliqué, mais il n'y a aucune excuse pour ne pas fournir de conversion intégrée entre différentes classes de temps intégrées. Vous pouvez lancer une RangeException si vous essayez d'obtenir un time_t UNIX pour 4713 BC (bien qu'une valeur négative BigNum serait plus agréable), mais fournissez au moins une méthode pour cela.
Mark Reed
1
Time#to_datetimesemble préserver tz pour moi:Time.local(0).to_datetime.zone #=> "-07:00"; Time.gm(0).to_datetime.zone #=> "+00:00"
Phrogz
Le décalage UTC @Phrogz n'est pas la même chose qu'un fuseau horaire. L'un est constant, l'autre peut changer à différents moments de l'année pour l'heure d'été. DateTime n'a pas de zone, il ignore l'heure d'été. Le temps le respecte, mais uniquement dans le TZ «local» (environnement système).
Andrew Vit
1
Amélioration de la solution Gordon Wilson, voici mon essai:
def to_time
#Convert a fraction of a day to a number of microseconds
usec =(sec_fraction *60*60*24*(10**6)).to_i
t =Time.gm(year, month, day, hour, min, sec, usec)
t - offset.abs.div(SECONDS_IN_DAY)end
Vous obtiendrez la même heure en UTC, perdant le fuseau horaire (malheureusement)
Aussi, si vous avez ruby 1.9, essayez simplement la to_timeméthode
Lors de ces conversions, il convient de prendre en compte le comportement des fuseaux horaires lors de la conversion d'un objet à l'autre. J'ai trouvé quelques bonnes notes et des exemples dans ce stackoverflow poste .
Réponses:
Vous aurez besoin de deux conversions légèrement différentes.
Pour convertir de
Time
en,DateTime
vous pouvez modifier la classe Time comme suit:Des ajustements similaires à Date vous permettront de convertir
DateTime
enTime
.Notez que vous devez choisir entre l'heure locale et l'heure GM / UTC.
Les deux extraits de code ci-dessus sont tirés de O'Reilly's Ruby Cookbook . Leur politique de réutilisation du code le permet.
la source
la source
En tant que mise à jour de l'état de l'écosystème Ruby
Date
,DateTime
etTime
ont maintenant des méthodes pour convertir entre les différentes classes. Utilisation de Ruby 1.9.2+:la source
1.9.3p327 :007 > ts = '2000-01-01 12:01:01 -0700' => "2000-01-01 12:01:01 -0700" 1.9.3p327 :009 > dt = ts.to_datetime => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :010 > dt.to_time => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :011 > dt.to_time.class => DateTime
Malheureusement, le
DateTime.to_time, Time.to_datetime
etTime.parse
fonctions ne conservent pas les informations de fuseau horaire. Tout est converti en fuseau horaire local lors de la conversion. L'arithmétique des dates fonctionne toujours, mais vous ne pourrez pas afficher les dates avec leurs fuseaux horaires d'origine. Ces informations contextuelles sont souvent importantes. Par exemple, si je souhaite voir les transactions effectuées pendant les heures de bureau à New York, je préfère probablement les voir affichées dans leur fuseau horaire d'origine, pas dans mon fuseau horaire local en Australie (qui est 12 heures avant New York).Les méthodes de conversion ci-dessous conservent ces informations tz.
Pour Ruby 1.8, regardez la réponse de Gordon Wilson . Il provient du bon vieux livre de recettes Ruby fiable.
Pour Ruby 1.9, c'est un peu plus facile.
Cela imprime ce qui suit
Les informations DateTime d'origine complètes, y compris le fuseau horaire, sont conservées.
la source
Time#to_datetime
semble préserver tz pour moi:Time.local(0).to_datetime.zone #=> "-07:00"; Time.gm(0).to_datetime.zone #=> "+00:00"
Amélioration de la solution Gordon Wilson, voici mon essai:
Vous obtiendrez la même heure en UTC, perdant le fuseau horaire (malheureusement)
Aussi, si vous avez ruby 1.9, essayez simplement la
to_time
méthodela source
Lors de ces conversions, il convient de prendre en compte le comportement des fuseaux horaires lors de la conversion d'un objet à l'autre. J'ai trouvé quelques bonnes notes et des exemples dans ce stackoverflow poste .
la source