diff --git a/token.tokens.inc b/token.tokens.inc
index 7685b63..b8608b4 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,16 @@ function field_tokens($type, $tokens, array $data = array(), array $options = ar
           }
         }
       }
+      elseif (in_array($field_item->getFieldDefinition()->getType(), ['datetime', 'daterange']) && in_array($property_name, ['date', 'start_date', 'end_date'])) {
+        $date_tokens = \Drupal::token()->findWithPrefix($tokens, $property_name);
+        if(isset($tokens[$property_name])) {
+          $date_tokens['raw'] = $tokens[$property_name];
+        }
+        if ($date_tokens) {
+          $datetime = $field_item->$property_name->getTimestamp();
+          $replacements += \Drupal::token()->generate('date', $date_tokens, ['date' => $datetime], $options, $bubbleable_metadata);
+        }
+      }
       else {
         $replacements[$original] = $field_item->$property_name;
       }
