Différence de gestion de dates Linux/WIndo ws?

Bonsoir,

J’ai un problème dans un modèle en voulant redéfinir une date lors de
son
affectation en migrant l’application sous windows. Je gère mes dates
dans
des formulaires sous la forme “%d/%m/%Y” je gère donc simplement
l’insertion
en base du champs date_naissance (datetime) :

Au départ, j’avais ceci :
def date_naissance=(value)
value =~ /(\d{2})/(\d{2})/(\d{4})/
self[:date_naissance] = “#{$3}-#{$2}-#{$1}”
end

Tout fonctionnait très bien jusqu’à que j’installe mon application sous
windows. J’ai les même environnements rails et ruby (v1.2.3 pour le
premier
et v1.8.5 pour le second et mysql 5 pour les 2) sur les deux OS.
Cependant, la gestion des dates sous windows est différente car je
n’arrive
pas à insérer des dates antérieures à 1970 alors que sous linux tout est
ok.
Mon champs en base se retrouve nil.

En fouinant, j’ai testé
self[:date_naissance]=DateTime.strptime("#{$3}-#{$2}-#{$1}","%Y-%m-%d")
mais sans conviction car çà ne résoud pas mon problème.
En anlysant cela à la console, j’ai pu remarquer que c’est la
transaction
avec l’action save qui pose problème mais sans savoir pourquoi .

Est ce que quelqu’un pourrait m’aider ? Pour être honnête c’est critique
car
je sèche complètement apres des jours d’essais …

Merci, Edouard

Hello Edouard

quel type MySql utilises-tu pour la colonne ?
disposes-tu de logs ActiveRecord à nous fournir ?

Thibaut

Bonjour,

le type mysql est du datetime.

Le seul message d’erreur que j’ai pu avoir en console c’est un “value
is out of range”. Sinon, aucun message, il positionne la date à nil
sans générer d’erreur.

Edouard

En regardant la documentation[1] de Mysql 5, j’ai pu constater que si
tu donnes ton ann�e en seulement 2 chiffres, ca prend uniquement entre
1970 et 2069.

Je pense vraiment que ton probl�me vient de MySQL plus que de Rails.

Regarde au niveau des requ�tes g�n�r�s et reproduit les dans ta console
MySQL.

Une fois que tu vois quel requ�te tu dois r�aliser, tu auras un d�but
de r�ponses.

Je cite la doc :

Dates containing two-digit year values are ambiguous because the
century is unknown. MySQL interprets two-digit year values using the
following rules:

*

  Year values in the range 00-69 are converted to 2000-2069.
*

  Year values in the range 70-99 are converted to 1970-1999.

[1] : http://dev.mysql.com/doc/refman/5.0/en/datetime.html

On 7/26/07, Edouard [email protected] wrote:


Cyril M.

Bonsoir,

malheureusement j’aurai préféré. Voici les 2 requêtes que j’ai extrait
de ma log depuis windows :

OK:

Parameters: {“membre”=>{“num_secu”=>“AZERTYUIOPQSD”,
“ville”=>“Toulon”, “nom”=>“Cante”, “nom_jeune_fille”=>“sdsqdsq”,
“nationalite”=>“sdsqdq”, “nb_enfants_a_charge”=>“0”,
“prenom”=>“sqdsqdsqdq”, “mobile”=>“dsdqsd”, “lieu”=>“sqdsqdq”,
“code_postal”=>“13422”, “fax”=>“sqdqsdqd”, “adresse”=>“34 FDEFSDF”,
“agephip”=>“true”, “telephone”=>“fjdnfjd”,
“situation_familiale”=>“Célibataire”, “date_naissance”=>“04/07/2007”,
“email”=>“[email protected]”}, “commit”=>“Valider”, “action”=>“update”,
“id”=>“1”, “controller”=>“admin/membre”, “goto”=>“show_membre”}

SQL
généré:UPDATE membres SET created_at = ‘2007-07-05 01:40:01’,
date_naissance = ‘2007-07-04 00:00:00’, categorie =
‘Puéricultrice’, nom = ‘Cante’, nationalite = ‘sdsqdq’, fax =
‘sqdqsdqd’, code_postal = ‘13422’, referent = 1, ville =
‘Toulon’, num_secu = ‘AZERTYUIOPQSD’, groupe = ‘Diplomé’,
prenom = ‘sqdsqdsqdq’, telephone = ‘fjdnfjd’, etablissement_id =
1, agephip = 1, adresse = ‘34 FDEFSDF’, nb_enfants_a_charge = 0,
email = ‘[email protected]’, mobile = ‘dsdqsd’, lieu = ‘sqdsqdq’,
situation_familiale = ‘Célibataire’, updated_at = ‘2007-07-26
19:12:09’, nom_jeune_fille = ‘sdsqdsq’ WHERE id = 1

KO:

Parameters: {“membre”=>{“num_secu”=>“AZERTYUIOPQSD”,
“ville”=>“Toulon”, “nom”=>“Cante”, “nom_jeune_fille”=>“sdsqdsq”,
“nationalite”=>“sdsqdq”, “nb_enfants_a_charge”=>“0”,
“prenom”=>“sqdsqdsqdq”, “mobile”=>“dsdqsd”, “lieu”=>“sqdsqdq”,
“code_postal”=>“13422”, “fax”=>“sqdqsdqd”, “adresse”=>“34 FDEFSDF”,
“agephip”=>“true”, “telephone”=>“fjdnfjd”,
“situation_familiale”=>“Célibataire”, “date_naissance”=>“04/07/1960”,
“email”=>“[email protected]”}, “commit”=>“Valider”, “action”=>“update”,
“id”=>“1”, “controller”=>“admin/membre”, “goto”=>“show_membre”}

SQL
généré:UPDATE membres SET created_at = ‘2007-07-05 01:40:01’,
date_naissance = NULL, categorie = ‘Puéricultrice’, nom =
‘Cante’, nationalite = ‘sdsqdq’, fax = ‘sqdqsdqd’, code_postal =
‘13422’, referent = 1, ville = ‘Toulon’, num_secu =
‘AZERTYUIOPQSD’, groupe = ‘Diplomé’, prenom = ‘sqdsqdsqdq’,
telephone = ‘fjdnfjd’, etablissement_id = 1, agephip = 1,
adresse = ‘34 FDEFSDF’, nb_enfants_a_charge = 0, email =
[email protected]’, mobile = ‘dsdqsd’, lieu = ‘sqdsqdq’,
situation_familiale = ‘Célibataire’, updated_at = ‘2007-07-26
19:12:49’, nom_jeune_fille = ‘sdsqdsq’ WHERE id = 1

Comme vous pouvez le voir, c’est bien la date fournie par rails qui
est en cause puisque la requête contient nil …

Je ne sais plus quoi faire car cela me parait si simple d’un point de
vue code que je n’arrive pas à voir où est la boulette. Je n’aime pas
windows (c’est pour une recette client que je l’ai installé) et là il
me le rend bien …

Edouard

Re,

j’ai encore poussé mes tests et cela va encore plus loin … j’ai
positionné un date_select pour ma saisie afin de garantir le format et
voila le resultat avec une date antérieure à 1970 :

1 error(s) on assignment of multiparameter attributes

RAILS_ROOT: C:/INSTAN~1/rails_apps/opale/config/…
Application Trace | Framework Trace | Full Trace

C:/INSTAN~1/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/
active_record/base.rb:2094:in
execute_callstack_for_multiparameter_attributes' C:/INSTAN~1/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/ active_record/base.rb:2074:inassign_multiparameter_attributes’
C:/INSTAN~1/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/
active_record/base.rb:1675:in attributes=' C:/INSTAN~1/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/ active_record/base.rb:1591:inupdate_attributes’
#{RAILS_ROOT}/app/controllers/admin/membre_controller.rb:115:in
`update’

Request

Parameters: {“membre”=>{“num_secu”=>“AZERTYUIOPQSD”,
“ville”=>“MArseille”, “nom”=>“Cante”, “nom_jeune_fille”=>“sdsqdsq”,
“nationalite”=>“sdsqdq”, “nb_enfants_a_charge”=>“0”,
“prenom”=>“sqdsqdsqdq”, “mobile”=>“dsdqsd”, “lieu”=>“sqdsqdq”,
“code_postal”=>“13422”, “date_naissance(1i)”=>“1960”,
“fax”=>“sqdqsdqd”, “adresse”=>“34 FDEFSDF”, “date_naissance(2i)”=>“7”,
“agephip”=>“true”, “telephone”=>“fjdnfjd”,
“situation_familiale”=>“Célibataire”, “date_naissance(3i)”=>“27”,
“email”=>“[email protected]”}, “commit”=>“Valider”, “id”=>“1”,
“goto”=>“show_membre”}

Est ce que quelqu’un a des formulaires avec dates sous windows qui
n’ont pas ce problème ? Je suis en train de remettre en cause bcp de
choses et je tourne autour du pot. Mysql peut gérer ces dates (saisie
manuelle dans phpmyadmin) mais Rails a des soucis que je ne comprends
pas.

Ma solution sale va être de mettre la date en varchar, mais bonjour la
rustine ! Si quelqu’un peut m’éclaircir les idées, çà m’éviterai de
refuser toute recette sur un portable windows la prochaine fois :slight_smile:

Edouard

On 7/27/07, Edouard [email protected] wrote:

RAILS_ROOT: C:/INSTAN~1/rails_apps/opale/config/…
active_record/base.rb:1591:in `update_attributes’
“fax”=>“sqdqsdqd”, “adresse”=>“34 FDEFSDF”, “date_naissance(2i)”=>“7”,

Ma solution sale va être de mettre la date en varchar, mais bonjour la
rustine ! Si quelqu’un peut m’éclaircir les idées, çà m’éviterai de
refuser toute recette sur un portable windows la prochaine fois :slight_smile:

En regardant un peu les source de Rails, j’ai pense que ton erreur
arrive au moment suivant :

Time == klass ? (@@default_timezone == :utc ? klass.utc(*values) :
klass.local(*values)) : klass.new(*values)

Pour voir l’erreur complete qui est remonté par cette erreur, tu peux
de façon temporaire et pour voir un peu l’erreur.

Commenter les lignes 2087, 2089, 2090 et 2091 qui sont dans le fichier
active_record/base.rb du paquet Active Record.

Je pense que le problème est au niveau de la définition de ton
default_timezone. qui est par défaut à :local

Ceci n’est qu’une piste.


Cyril M.

Probleme ultra classique du stockage des dates par les OS, ce n est pas
directement lie a ruby on peut etre confronte a ce genre de probleme en
C ou
en php mais simplement au fait que les dates sont nativement stockee en
time
after epoch = timestamp > 0 (un timestamp prend son origine au 1-1-1970
sur
unix et ca varie ensuite suivant les OS).

Je vais peut-etre dire des betises mais un specialiste des
fonctionnements
internes de ruby corrigera si c est le cas. Time repose sur l
implememtation
system des timestamp et est donc potentiellement limite par ce genre de
contrainte. En revanche Datetime est en pure ruby et devrait donc regler
ton
probleme. Sauf aue tel aue tu decris le probleme ca a plus l air d etre
lie
au driver mssql, peut etre jeter un coup d oeil la
http://dev.rubyonrails.org/ticket/3430

En tout cas ca ne doit pas etre tres complique a tracer a priori.

Ps: desole pour les accents, clavier jap…

Bonjour à tous,

en effet mes tests m’ont ammené à penser que cela viens du connecteur
Mysql/Ruby sous windows car si je génère un DateTime sous Ruby sans
l’enregistrer en base ok, si j’insere via phpMyAdmin une valeur avant
1970 ok. C’est donc la connection entre ruby et mysql le malaise.

Renaud, merci pour ce billet j’avais eu du mal à le trouver, mais
tournant sous mysql, j’ai compris l’erreur potentielle de mon
connecteur, mais je n’y ai pas trouvé de solution.

N’ayant pas de traitement particulier, j’ai en effet pris l’option du
varchar pour les dates de naissance et je reste en datetime pour le
reste. Je continuerai à chercher car je veux pas rester sur ma faim.
Je vous tient au courant si j’avance sur le problème.

Merci encore pour votre aide !

Edouard

Une bonne piste je pense.

En effet en effectuant un petit :

Time.local(1960) dans un IRB classique j’obtiens un :

out of range.

Même combat avec Time.utc

Je pense que le problème vient presque de Ruby sous Windows

On 7/27/07, Cyril M. [email protected] wrote:

C:/INSTAN~1/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/
“code_postal”=>“13422”, “date_naissance(1i)”=>“1960”,
pas.
klass.local(*values)) : klass.new(*values)
Ceci n’est qu’une piste.


Cyril M.


Cyril M.

Édouard :

N’ayant pas de traitement particulier, j’ai en effet pris l’option du
varchar pour les dates de naissance et je reste en datetime pour le
reste. Je continuerai à chercher car je veux pas rester sur ma faim.
Je vous tient au courant si j’avance sur le problème.

Je me contenterai d’une seule remarque sur ce sujet.

Je n’ai pas vraiment compris pourquoi tu utilisais dans ta table,
une colonne de type DATETIME alors que tu ne demandes à tes utilisateurs
que de rentrer les infos jour/mois/année. (Déjà il faut avoir de sacrées
bonnes raisons pour leur demander l’heure de leur naissance : genre
je fais une appli qui va permettre à Françoise Hardy de connaître
la position des planètes dans le ciel lors de leur naissance et en
déduire leur thème astral : autant dire que généralement, on s’en tape
le caribou.) Avec une colonne DATE, tu as une plage de valeurs
suffisantes que ce soit sous MySQL ou Ruby, ce qui te permet même
de t’affranchir du bug de l’année 2038.

– Jean-François.


Ruby ( http://www.rubyfrance.org ) on Rails ( http://www.railsfrance.org
)

Bonjour Jean-françois,

sache que le problème était également rencontré sur les types date (ce
que j’avais au début). Et je peux t’assurer que j’ai fait les même
tests pour les 2 types de champs.
Je me suis tourné vers le datetime après mes recherches sur le net. Le
problème ne vient pas d’une plage de valeur Mysql ou Ruby, c’est lié à
l’environnement Windows !! La gestion de mon champs marchait très bien
sous Linux avant que je la porte sous windows.

Edouard