2009-04-18 5 views
3

En arrière-plan, il existe plusieurs façons de stocker des dates dans MySQ.Définition d'une table avec sqlalchemy avec un horodatage mysql unix

  1. En tant que chaîne, par ex. "09/09/2009".
  2. En tant qu'entier à l'aide de la fonction UNIX_TIMESTAMP(), il s'agit supposément de la représentation traditionnelle de l'heure unix (vous connaissez les secondes depuis l'époque plus/moins les secondes bissextiles).
  3. En tant que TIMESTAMP de MySQL, un type de données spécifique à mysql n'est pas identique à un horodatage unix.
  4. En tant que champ de date MySQL, un autre type de données spécifique à mysql.

    Il est très important de ne pas confondre le cas 2 avec le cas 3 (ou le cas 4). J'ai une table existante avec un champ de date entier (cas 2) comment puis-je le définir dans sqlalchemy d'une manière que je n'ai pas besoin d'accéder à la fonction "FROM_UNIXTIME" de mysql? Pour l'anecdote, en utilisant simplement sqlalchemy.types.DateTime et en espérant faire ce qui est juste quand il détecte qu'une colonne entière ne fonctionne pas, cela fonctionne pour les champs d'horodatage et les champs de date.

Répondre

6

Je pense qu'il y a quelques problèmes avec le type décorateur que vous avez montré.

  1. impl devrait être sqlalchemy.types.Integer au lieu de DateTime.
  2. Le décorateur doit autoriser les colonnes NULL.

Voici le ce que je pense:


import datetime, time 
from sqlalchemy.types import TypeDecorator, DateTime, Integer 

class IntegerDateTime(TypeDecorator): 
    """a type that decorates DateTime, converts to unix time on 
    the way in and to datetime.datetime objects on the way out.""" 
    impl = Integer # In schema, you want these datetimes to 
        # be stored as integers. 
    def process_bind_param(self, value, _): 
     """Assumes a datetime.datetime""" 
     if value is None: 
      return None # support nullability 
     elif isinstance(value, datetime.datetime): 
      return int(time.mktime(value.timetuple())) 
     raise ValueError("Can operate only on datetime values. " 
         "Offending value type: {0}".format(type(value).__name__)) 
    def process_result_value(self, value, _): 
     if value is not None: # support nullability 
      return datetime.datetime.fromtimestamp(float(value)) 
+0

Ok je l'aime, dommage cela n'a pas participé à la production à la fin. Mais pourquoi avez-vous remplacé le moteur par _? – rgz

+0

Juste une habitude. pylint n'aime pas les variables inutilisées, donc par convention nous utilisons _. –

2

Alors oui, cette approche fonctionne. Et j'ai fini par répondre à ma propre question: /, j'espère que quelqu'un trouvera cela utile.

import datetime, time 
from sqlalchemy.types import TypeDecorator, DateTime 
class IntegerDateTime(TypeDecorator): 
    """a type that decorates DateTime, converts to unix time on 
    the way in and to datetime.datetime objects on the way out.""" 
    impl = DateTime 
    def process_bind_param(self, value, engine): 
     """Assumes a datetime.datetime""" 
     assert isinstance(value, datetime.datetime) 
     return int(time.mktime(value.timetuple())) 
    def process_result_value(self, value, engine): 
     return datetime.datetime.fromtimestamp(float(value)) 
    def copy(self): 
     return IntegerDateTime(timezone=self.timezone) 
Questions connexes