Repository: tobymao/sqlglot

Issue:
Inaccurate sql generation for DATEPART in T-SQL
Similar to [2586](https://github.com/tobymao/sqlglot/issues/2586) DATEPART function fails for HOUR and WEEKDAY

**Fully reproducible code snippet**
```
query = """SELECT DATEPART(HOUR, date_and_time) AS 'Hour' FROM table """
print(parse_one(quarter_query, 'tsql').sql(dialect='tsql'))

```
this gives `SELECT FORMAT(CAST(date_and_time AS DATETIME2), 'hour') AS "Hour" FROM table` but the [format code](https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings) is 'h' . Similarly for WEEKDAY it gives 'dw' which is not present in the format codes(thought I couldnt find a corresponding code)


Discussion:

Patch:
diff --git a/sqlglot/dialects/tsql.py b/sqlglot/dialects/tsql.py
index 03f8537b..a60891fe 100644
--- a/sqlglot/dialects/tsql.py
+++ b/sqlglot/dialects/tsql.py
@@ -136,6 +136,9 @@ def _parse_hashbytes(args: t.List) -> exp.Expression:
     return exp.func("HASHBYTES", *args)
 
 
+DATEPART_ONLY_FORMATS = {"dw", "hour", "quarter"}
+
+
 def _format_sql(self: TSQL.Generator, expression: exp.NumberToStr | exp.TimeToStr) -> str:
     fmt = (
         expression.args["format"]
@@ -149,8 +152,8 @@ def _format_sql(self: TSQL.Generator, expression: exp.NumberToStr | exp.TimeToSt
     )
 
     # There is no format for "quarter"
-    if fmt.name.lower() == "quarter":
-        return self.func("DATEPART", "QUARTER", expression.this)
+    if fmt.name.lower() in DATEPART_ONLY_FORMATS:
+        return self.func("DATEPART", fmt.name, expression.this)
 
     return self.func("FORMAT", expression.this, fmt, expression.args.get("culture"))
 


Test patch:
diff --git a/tests/dialects/test_tsql.py b/tests/dialects/test_tsql.py
index 897aa24f..88d1ebcb 100644
--- a/tests/dialects/test_tsql.py
+++ b/tests/dialects/test_tsql.py
@@ -891,8 +891,26 @@ WHERE
         )
 
     def test_datepart(self):
-        self.validate_identity("DATEPART(QUARTER, x)", "DATEPART(QUARTER, CAST(x AS DATETIME2))")
-        self.validate_identity("DATEPART(YEAR, x)", "FORMAT(CAST(x AS DATETIME2), 'yyyy')")
+        self.validate_identity(
+            "DATEPART(QUARTER, x)",
+            "DATEPART(quarter, CAST(x AS DATETIME2))",
+        )
+        self.validate_identity(
+            "DATEPART(YEAR, x)",
+            "FORMAT(CAST(x AS DATETIME2), 'yyyy')",
+        )
+        self.validate_identity(
+            "DATEPART(HOUR, date_and_time)",
+            "DATEPART(hour, CAST(date_and_time AS DATETIME2))",
+        )
+        self.validate_identity(
+            "DATEPART(WEEKDAY, date_and_time)",
+            "DATEPART(dw, CAST(date_and_time AS DATETIME2))",
+        )
+        self.validate_identity(
+            "DATEPART(DW, date_and_time)",
+            "DATEPART(dw, CAST(date_and_time AS DATETIME2))",
+        )
 
         self.validate_all(
             "SELECT DATEPART(month,'1970-01-01')",