Repository: moment/luxon (js)

Issue:
throwOnInvalid does not throw for invalid year
**Describe the bug**
When setting `Settings.throwOnInvalid`, Luxon does not seem to throw an error if the year is too large (both positive or negative), even though `dateTime.isValid` will return `false`.

**To Reproduce**

```ts
luxon.Settings.throwOnInvalid = true;

const dateTime = luxon.DateTime.fromObject({ year: 1000000 });
console.log(dateTime.isValid, dateTime.invalidReason);
```

**Actual vs Expected behavior**

Expected: An error is thrown

Actual: `false invalid input` is logged to the console

**Desktop:**

- OS: macOS 13.4
- Browser: Chrome 114
- Luxon version: 3.3.0
- Your timezone: Europe/Berlin

Thanks for looking into it!

Pull request:
fix: DateTime throws when year is invalid and throwOnInvalid is true
Fixes #1449.

### What I did

So the issue here is that whenever the year passed is too big, `DateTime.fromObject` goes all the way through execution and ends up returning the DateTime instance.

The instance, which is being instantiated [here](https://github.com/moment/luxon/blob/master/src/datetime.js#L798), is invalid. This is because DateTime's constructor checks on the year [here](https://github.com/moment/luxon/blob/master/src/datetime.js#L492) and assigns `invalid`. The problem is that, unlike other invalid cases, in this one (and probably others) we never go through `DateTime.invalid`, therefore we do not check on `throwIfInvalid` (and eventually throw).

So here I'm checking if the DateTime instance is invalid before returning, and if it is, i'm going through the same `DateTime.invalid` method. 

The good thing is that we're reusing the same logic for throwing. The not so good thing is that, should `throwIfInvalid` be `false`, we would be returning basically the same thing that we started with. But I think this is a good compromise!

I've also added a unit test.

Patch:
diff --git a/src/datetime.js b/src/datetime.js
index f98d183f..9472cb53 100644
--- a/src/datetime.js
+++ b/src/datetime.js
@@ -810,6 +810,10 @@ export default class DateTime {
       );
     }
 
+    if (!inst.isValid) {
+      return DateTime.invalid(inst.invalid);
+    }
+
     return inst;
   }
 


Test patch:
diff --git a/test/datetime/invalid.test.js b/test/datetime/invalid.test.js
index a776e185..d13fb864 100644
--- a/test/datetime/invalid.test.js
+++ b/test/datetime/invalid.test.js
@@ -72,3 +72,18 @@ test("throwOnInvalid throws", () => {
 test("DateTime.invalid throws if you don't provide a reason", () => {
   expect(() => DateTime.invalid()).toThrow();
 });
+
+test("throwOnInvalid throws if year is too big", () => {
+  try {
+    Settings.throwOnInvalid = true;
+    expect(() =>
+      DateTime.fromObject({
+        year: 9999999,
+        month: 5,
+        day: 25,
+      })
+    ).toThrow();
+  } finally {
+    Settings.throwOnInvalid = false;
+  }
+});