The place for apps & thoughts

Swift on server – Part 3: Handling Date type with Vapor / PostgreSQL

In this Part 3 (final one), I’ll show you how to handle Date types. This works with PostgreSQL, should work about the same with MariaDB/MySQL, but couldn’t make it work with MongoDB (see the conclusion for a tip).

If you missed:
In Part 1 of this series of articles I went through installing Swift, Vapor and PostgreSQL.
In Part 2 I created an app using Vapor and do the saving and retrieving of an object from the Postgres database. The model us just basic types Int & String (Double is also supported by Vapor).

Vapor 2.0 (and Fluent 2.0 – the database framework used by Vapor) are currently in alpha versions. The final releases should include date handling. Since then, here’s my workaround.

So at this time the User model looks like:

First, let’s change the prepare function to make a Timestamp type column instead of Varchar for lastconnection.

As Timestamp (or DateTime for MariaDB/MySQL) is not a basic type known by the framework we have to use the custom type and precise the database specific type.

Next let’s change the User model’s lastconnection type to Date:

And fix the init:

Now the delicate part, fixing init(node…) and makeNode functions.
The Node type does not handle Date, so the workaround in order to keep the database column as Date/Timestamp is to transform it from String to Date when read from database, and from Date to String when writing to database. This works because Postgres and MariaDB/MySQL return the Timestamp type (for Postgres, DateTime for MariaDB) as String. Just connect to your database and do a Select on a table with a Timestamp column and you’ll see.

So let’s write transformation functions from Date to String and from String to Date.

You can also extend the Date class with these functions instead of a specific model if you want to share the functions between several models. In this example we just have one model, so I just added them to the model.

And let’s use them.

And then, let’s fix main.swift
Change users route to:

And the createusers route:

Now build the project:

Before running, let’s revert the previous created table.
For that, run in a terminal:

and answer y when asked.

If you check the Postgres database you should no longer see fluent and users tables.

Now ready for run:

If we check the database there should be a Users table looking like:

And if you browse to the url: http://localhost:8080/createusers
and check the database you should see the users:

And you should also get the same if you browse to the url: http://localhost:8080/allusers

Also works the creation of a new user using the Rest client and POST to the route: http://localhost:8080/user

So to finish here’s the final main.swift:

And User.swift:

That’s the trick, just transform Date to String and String to Date. Pay attention to the format (MySQL does not have the milliseconds).

It took me some time to figure it out, especially as I started with a MongoDB database at first where the trick it doesn’t work (I guess you can achieve the same result with MongoDB using a Timestamp type for the column instead of Date and transforming from Int to Date and Date to Int, but I didn’t want to change my database column format). I did found a lot of Vapor tutorials (big shout out to Ray Wenderlich‘s screencasts who initiated me to Swift on Server using Vapor) but none was using dates.

If anyone else is struggling with this, I hope these posts will help.