Medium.com-style time to read counter

in code


Like it or not as you will, but Medium has come to prominence lately as a place for thoughtful curated articles. Among other features that have caught my eye is the time to read counter, as shown in the topright corner of this screenshot:

medium.com article screenshot

Depending on your desired level of accuracy in the counter (you can give an estimate almost down to the second), it can be easy or hard to do:

  1. Get word count of article.
  2. Get the average per-minute word count for an adult, and divide the article into this.
  3. Round either up or down to reach the nearest minute.
  4. (Optionally!) Turn this number into words.

To go beyond the basic solution: you could dive into per-word complexity and comprehension in a manner similar to Hemingway. Time average comprehension and reading time on a per-word basis, or track reading time for a sample set of articles by a random set of mixed lay and adept readers.

Words per minute
Reading speed doesn’t equal comprehension speed. Most people can read and recite quickly, but comprehension and retention will come more slowly. I’m above average-I clock in the ~513 WPM reading range, as averaged from three runs on the Staples speed-reading test. I am an avid and regular reader with a broad vocabulary, so don’t consider this empirical. A Forbes article gives a range of reading speeds, with an adult average of 300 words per minute. I think Medium will use a higher WPM number than this, because:

  1. A shorter given read time is more likely to lead to engagement. Time is precious after all.
  2. A higher assumed reading time will flatter in these circumstances. If you’re flattered, then you feel good.
  3. I have a suspicion that many readers on Medium are possibly already above average readers given their demographic (technically educated?).

But the most empirical WPM count I have remains 300, or 5 words per second.

Post WPM count
Word count in an article can vary by dependent on how you parse present markdown. Take the post “PSR J1719-1438 b’s surface gravity” and its mix of words and arithmetic:

  • The WordPress editor reports 165 words.
  • wc -w in the Bash shell reports 197 words.
  • str_word_count() without strip_tags() reports 270 words.
  • str_word_count() with strip_tags() reports 124 words.

I will use str_word_count(strip_tags($article) for this.
Words per second = words per minute, rounded.
Reading time = word count / words per second:

function rmwb_reading_seconds($post) {
    $average_wpm = 300;
    $average_wps = round($average_wpm / 60);
    $time = str_word_count(strip_tags($post));
    return round($time / $average_wps);
}

Medium rounds this time to the nearest minute. So will I:

function rmwb_reading_minutes($seconds) {
    if ($seconds % 60 <= 30) {
        $minutes = floor($seconds / 60);
    } else {
        $minutes = ceil($seconds / 60);
    }

    return $minutes;
}

Call it all with:

function rmwb_reading_time($post) {
    $time = rmwb_reading_seconds($post);
    $time = rmwb_reading_minutes($time);
    $time_word = rmwb_minutes_to_words($time);
    $min_word = ($time <= 1) ? ' minute.' : ' minutes.';
    return ucfirst($time_word) . $min_word;
}

That’s it-you now have a medium.com-style time counter for your website.

Time to words
If you want to go be fancy and convert the minutes to words, then add this function too. The method I use for this is fairly close to my solution for Problem 17 of Project Euler.

function rmwb_minutes_to_words($minutes) {
    $time_word = '';

    $singles = array(
        'one','two','three','four','five',
        'six','seven','eight','nine'
    );

    $teens = array(
        'eleven', 'twelve','thirteen','fourteen','fifteen',
        'sixteen','seventeen','eighteen','nineteen'
    );

    $tens = array(
        'ten','twenty','thirty','forty','fifty',
        'sixty','seventy','eighty','ninety'
    );

    if ($minutes <= 0) {
        // < 0 - 0
        $time_word = $singles[0];
    } elseif ($minutes < 10) {
        // 1 - 9
        $time_word = $singles[$minutes - 1];
    } elseif ($minutes > 10 && $minutes < 20) {
        // 11 - 19
        $time_word = $teens[$minutes - 11];
    } elseif ($minutes % 10 == 0) {
        // 10, 20, etc.
        $time_word = $tens[($minutes / 10) - 1];
    } elseif ($minutes > 99) {
        // > 99
        $a = $tens[8];   
        $b = $singles[8];
        $time_word = 'greater than' . $a . '-' . $b;
    } else {
        // 31, 56, 77, etc.
        $a = $tens[($minutes % 100) / 10 - 1];   
        $b = $singles[($minutes % 10) - 1];
        $time_word = $a . '-' . $b;
    } 

    return $time_word;
}


Remap a JavaScript Object

in code

Blog Silence

in me

Run Clare 2019 Race Series

in running


Your email address will not be published. Required fields are marked *