npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dtd2mysql

v11.2.0

Published

Command line tool to put the GB rail DTD feed into a MySQL compatible database

Readme

npm npm

dtd2mysql

An import tool for the British rail fares, routeing and timetable feeds into a database.

Although both the timetable and fares feed are open data you will need to obtain the fares feed via the ATOC website. The formal specification for the data inside the feed also available on the ATOC website.

At the moment only MySQL compatible databases are supported but it could be extended to support other data stores. PRs are very welcome.

Requirements

Node.js 22 or later. Date handling uses Temporal, through temporal-polyfill, which hands over to the built-in global on the versions that have one - Node 26 and later.

Download / Install

You don't have to install it globally but it makes it easier if you are not going to use it as part of another project. The -g option usually requires sudo. It is not necessary to git clone this repository unless you would like to contribute.

npm install -g dtd2mysql

Fares

Each of these commands relies on the database settings being set in the environment variables. For example DATABASE_USERNAME=root DATABASE_NAME=fares dtd2mysql --fares-clean.

Import

Import the fares into a database, creating the schema if necessary. This operation is destructive and will remove any existing data.

dtd2mysql --fares /path/to/RJFAFxxx.ZIP

Clean

Removes expired data and invalid fares, corrects railcard passenger quantities, adds full date entries to restriction date records. This command will occasionally fail due to a MySQL timeout (depending on hardware), re-running the command should correct the problem.

dtd2mysql --fares-clean

Timetables

Import

Import the timetable information into a database, creating the schema if necessary. This operation is destructive and will remove any existing data.

dtd2mysql --timetable /path/to/RJTTFxxx.ZIP

Convert to GTFS

Convert the DTD/TTIS version of the timetable (up to 3 months into the future) to GTFS.

dtd2mysql --timetable /path/to/RJTTFxxx.ZIP
dtd2mysql --gtfs-zip filename-of-gtfs.zip

--gtfs writes the same feed as a directory of text files instead of a zip, which is easier to read and to diff:

dtd2mysql --gtfs /path/to/output/

How far ahead the feed reaches, and the date it is built for, come from GTFS_RANGE and GTFS_TODAY. Pinning GTFS_TODAY makes a build reproducible.

GTFS_TODAY=2026-08-10 GTFS_RANGE="6 MONTH" dtd2mysql --gtfs /path/to/output/

The locations a service runs through without stopping are dropped. To keep them, as calls with pickup_type and drop_off_type of 1 and the pass time as both the arrival and the departure:

dtd2mysql --gtfs /path/to/output/ --remove-passing-points=false

It is roughly a fifth more stop times, and GTFS_REMOVE_PASSING_POINTS=0 says the same thing.

Import a GTFS feed

Load a GTFS feed back into the database, which is how the fares and routeing data are joined to it.

dtd2mysql --gtfs-import /path/to/gtfs/

Routeing Guide

Import

dtd2mysql --routeing /path/to/RJRGxxxx.ZIP
# optional
dtd2mysql --nfm64 /path/to/nfm64.zip 

Download from SFTP server

The download commands will take the latest full refresh from an SFTP server (by default the DTD server).

Requires the following environment variables:

SFTP_USERNAME=dtd_username
SFTP_PASSWORD=dtd_password
SFTP_HOSTNAME=dtd_hostname (this will default to dtd.atocrsp.org)

There is a command for each feed

dtd2mysql --download-fares /path/
dtd2mysql --download-timetable /path/
dtd2mysql --download-routeing /path/
dtd2mysql --download-nfm64 /path/

Or download and process in one command

dtd2mysql --get-fares
dtd2mysql --get-timetable
dtd2mysql --get-routeing
dtd2mysql --get-nfm64

Notes

null values

Values marked as all asterisks, empty spaces, or in the case of dates - zeros, are set to null. This is to preverse the integrity of the column type. For instance a route code is numerical although the data feed often uses ***** to signify any so this value is converted to null.

keys

Although every record format has a composite key defined in the specification an id field is added as the fields in the composite key are sometimes null. This is no longer supported in modern versions of MariaDB or MySQL.

missing data

At present journey segments, class legends, rounding rules, print formats and the fares data feed meta data are not imported. They are either deprecated or irrelevant. Raise an issue or PR if you would like them added.

timetable format

The timetable data does not map to a relational database in a very logical fashion so all LO, LI and LT records map to a single stop_time table.

GTFS feed cutoff date

Only schedule records that start up to 3 months into the future (using date of import as a reference point) are exported to GTFS for performance reasons. This will cause any data after that point to be either incomplete or incorrect, as override/cancellation records after that will be ignored as well.

Contributing

Issues, pull requests and the source live at planarnetwork/gb-transit. This package is apps/dtd2mysql in that repository; see its README for how the workspaces fit together.

License

This software is licensed under GNU GPLv3.

Copyright 2017 Linus Norton.