This works as a module, but think it should go in my .theme file instead This is some code which we're using to merge together content types into the body of an article:

&lt;?php

function remove_p($string) {
  $first_p=substr($string,0,3);
  if($first_p=="&lt;p&gt;") {
    $string=str_replace('&lt;p&gt;','',$string,$temp=1);
  }
  return $string;
}


function custom_press_release_node_view(array &amp;$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {

  $node_array = $build['#node']-&gt;toArray();
  if ($node_array['type'][0]['target_id'] == 'press_release' || $node_array['type'][0]['target_id'] == 'article') {

    // Get the location entity ID
    $field_name = $entity-&gt;get('field_office_location')-&gt;getValue();

    $location_id = $field_name[0]['target_id'];

    // Get the location name
    $term_object = \Drupal::entityTypeManager()-&gt;getStorage('taxonomy_term')-&gt;load($location_id);

    if(is_object($term_object)) {
      $term_array = $term_object-&gt;toArray();
    }

    // Generate output like - December 5, 2017
    $new_time_format = date('F d, Y', strtotime(substr($build['created'][0]['#markup'], 0, -7)));

    // Body text from Drupal
    $old_body = $build['body'][0]['#text'];

    $body = '&lt;p&gt;&lt;strong&gt;';
    if (is_array($term_array)) {
      $body .= $term_array['name'][0]['value'] . ', ';
    }
    $body .= $new_time_format . ' – &lt;/strong&gt;';
    $body .= remove_p($old_body) . '&lt;/p&gt;';

    // Modified body text
    $build['body'][0]['#text'] = $body;

  }

}


I think that this would be better done in my theme file, but we weren't able to call the functions we needed within the theme. 

Did we just miss something, or is this something that just needs to be done as a separate module?
What you missed is, that you can achieve all that output manipulation by just using the admin UI and view modes. It has the benefit of you being able to adjust the output order and available fields without having to touch any code. And gives you more power and flexibility to administer how content is displayed.

By incident, your solution matches a question answered just recently here: How to modify the value of a taxonomy field of a node using hook_node_view()?

Please have a look to my answer there, which describes how to show a field of the the taxonomy terms on the nodes by using the UI. 

You can easily adjust the proceedings by e.g. creating a dedicated display mode for your content nodes instead and adding the required fields there.

Additionally, you like to show the formatted created time, which you can either preprocess within a theme's hook_preprocess_HOOK() (so for example yourtheme_preprocess_node()), but also have already exposed within the template variables as {{ date }} in your node.html.twig template.