diff --git a/token.tokens.inc b/token.tokens.inc
index 7685b63..9c0bd08 100644
--- a/token.tokens.inc
+++ b/token.tokens.inc
@@ -1334,6 +1334,20 @@ function field_token_info_alter(&$info) {
           ];
         }
       }
+      // Provide format token for datetime fields.
+      if ($field->getType() == 'datetime') {
+        $info['tokens'][$field_token_name]['date'] = $info['tokens'][$field_token_name]['value'];
+        $info['tokens'][$field_token_name]['date']['name'] .= ' ' . t('format');
+        $info['tokens'][$field_token_name]['date']['type'] = 'date';
+      }
+      if ($field->getType() == 'daterange') {
+        $info['tokens'][$field_token_name]['start_date'] = $info['tokens'][$field_token_name]['value'];
+        $info['tokens'][$field_token_name]['start_date']['name'] .= ' ' . t('format');
+        $info['tokens'][$field_token_name]['start_date']['type'] = 'date';
+        $info['tokens'][$field_token_name]['end_date'] = $info['tokens'][$field_token_name]['end_value'];
+        $info['tokens'][$field_token_name]['end_date']['name'] .= ' ' . t('format');
+        $info['tokens'][$field_token_name]['end_date']['type'] = 'date';
+      }
     }
   }
 }
@@ -1565,6 +1579,18 @@ function field_tokens($type, $tokens, array $data = array(), array $options = ar
           }
         }
       }
+      elseif (in_array($field_item->getFieldDefinition()->getType(), ['datetime', 'daterange'])) {
+        $properties = ['date', 'start_date', 'end_date'];
+        foreach ($properties as $property) {
+          if($field_item->$property) {
+            $date_tokens = \Drupal::token()->findWithPrefix($tokens, $property);
+            if ($date_tokens) {
+              $datetime = $field_item->$property->getTimestamp();
+              $replacements += \Drupal::token()->generate('date', $date_tokens, ['date' => $datetime], $options, $bubbleable_metadata);
+            }
+          }
+        }
+      }
       else {
         $replacements[$original] = $field_item->$property_name;
       }
