<commit_before>var tokenizer = require('./src/tokenizer')
var compiler = require('./src/compiler')

module.exports = function(format) {

    if (typeof format !== 'string') {
        throw new TypeError('The formatter requires a string format!')
    }

    var tokens = tokenizer(format)
    var compiled = compiler(tokens)

    var format = {
        _compiled: compiled,
        format: function(time) {
            if (typeof time === 'number') {
                if (time === NaN) {
                    throw new TypeError('The time may not be NaN!')
                }
                // Parse an timeing object from the number
                time = {
                    hours: (time / 3600000) | 0,
                    minutes: ((time / 60000) | 0) % 60,
                    seconds: ((time / 1000) | 0) % 60,
                    milliseconds: time % 1000,
                }
            }

            if (typeof time === 'object') {
                if (time === null) {
                    throw new TypeError('The time may not be null!')
                }
                if (Array.isArray(time)) {
                    throw new TypeError('The time may not be an array!')
                }
            }

            let build = ''
            let len = this._compiled.length

            for (var i = 0; i < len; i++) {
                var part = this._compiled[i]

                if (typeof part === 'string') {
                    build += part
                    continue
                }

                if (typeof part !== 'object' || part === null || Array.isArray(part)) {
                    throw new Error('The compiled data contains invalid parts!')
                }

                var value = 0
                var stillShow = false
                switch (part.type) {
                case 'hh':
                case 'h':
                    value = time.hours
                    break
                case 'mm':
                case 'm':
                    stillShow = time.hours > 0
                    value = time.minutes
                    break
                case 'ss':
                case 's':
                    stillShow = time.hours > 0 || time.minutes > 0
                    value = time.seconds
                    break
                case 'ddd':
                case 'dd':
                case 'd':
                    stillShow = time.hours > 0 || time.minutes > 0 || time.seconds > 0
                    value = time.milliseconds
                    break
                default:
                    throw new Error('Invalid type "' + part.type + '" in the compiled data!')
                }
                if (!part.optional || (part.optional && stillShow)) {
                    build += this._formatTimePart(part.type, value)
                }
            }

            console.log(build)

            return build
        },
        _formatTimePart(type, value) {
            switch (type) {
            case 'h':
            case 'm':
            case 's':
                return (value > 0) ? value : ''
            case 'hh':
            case 'mm':
            case 'ss':
                return (value < 10) ? '0' + value : value
            case 'd':
                return (value > 0) ? value : ''
            case 'dd':
                return (value < 10) ? '0' + value : value
            case 'ddd':
                return (value < 10) ? '00' + value : ((value < 100) ? '0' + value :  value)
            }
        }
    }

    return format
}<commit_msg>Fixed formatter<commit_after>var tokenizer = require('./src/tokenizer')
var compiler = require('./src/compiler')

module.exports = function(formatString) {

    if (typeof formatString !== 'string') {
        throw new TypeError('The formatter requires a string format!')
    }

    var tokens = tokenizer(formatString)
    var compiled = compiler(tokens)

    var format = {
        _tokens: tokens,
        _compiled: compiled,
        asTime: function(data) {
            if (typeof data === 'undefined' || data === null) {
                throw new TypeError('The time may not be null/undefined!')
            }
            if (typeof data === 'number') {
                if (isNaN(data)) {
                    throw new TypeError('The time may not be NaN!')
                }
                // Parse an timeing object from the number
                return {
                    hours: (data / 3600000) | 0,
                    minutes: ((data / 60000) | 0) % 60,
                    seconds: ((data / 1000) | 0) % 60,
                    milliseconds: data % 1000,
                }
            }
            if (typeof data === 'object') {
                if (Array.isArray(data)) {
                    throw new TypeError('The time may not be an array!')
                }
                return Object.assign({
                    hours: 0,
                    minutes: 0,
                    seconds: 0,
                    milliseconds: 0
                }, data)
            }
            throw new TypeError('Invalid type "' + typeof data + '"!')
        },
        format: function(data) {
            var time = this.asTime(data)
            var build = ''
            var arr = []
            
            if (time.hours > 0) {
                arr = this._compiled.h
            } else if (time.minutes > 0) {
                arr = this._compiled.m
            } else if (time.seconds > 0) {
                arr = this._compiled.s
            } else if (time.milliseconds > 0) {
                arr = this._compiled.d
            }

            var len = arr.length
            for (var i = 0; i < len; i++) {
                var part = arr[i]

                if (typeof part === 'string') {
                    build += part
                    continue
                }

                build += this._formatTimePart(part.type, time)
            }

            return build
        },
        _formatTimePart(type, time) {
            var value = 0

            switch (type) {
                case 'h':
                case 'hh':
                    value = time.hours
                    break
                case 'm':
                case 'mm':
                    value = time.minutes
                    break
                case 's':
                case 'ss':
                    value = time.seconds
                    break
                case 'd':
                case 'dd':
                case 'ddd':
                    value = time.milliseconds
                    break
            }

            switch (type) {
                case 'h':
                case 'm':
                case 's':
                    return (value > 0) ? value : ''
                case 'hh':
                case 'mm':
                case 'ss':
                    return (value < 10) ? '0' + value : value
                case 'd':
                    return (value > 0) ? value : ''
                case 'dd':
                    return (value < 10) ? '0' + value : value
                case 'ddd':
                    return (value < 10) ? '00' + value : ((value < 100) ? '0' + value :  value)
            }
        }
    }

    return format
}
{'fraction_non_alphanumeric': 0.10611961057023644, 'fraction_numerical': 0.014464534075104311, 'mean_word_length': 0.9540760869565217, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1927590', 'n_tokens_mistral': 1944, 'n_tokens_neox': 1690, 'n_words': 528}