@rvoh/dream 2.3.0-alpha.5 → 2.3.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/Dream.js +2 -40
- package/dist/cjs/src/cli/index.js +4 -0
- package/dist/cjs/src/dream/Query.js +14 -11
- package/dist/cjs/src/dream/QueryDriver/Base.js +0 -14
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +86 -74
- package/dist/cjs/src/dream/QueryDriver/Postgres.js +10 -2
- package/dist/cjs/src/dream/internal/extractAssignableAssociationAttributes.js +9 -0
- package/dist/cjs/src/errors/db/DataIncompatibleWithDatabaseField.js +1 -3
- package/dist/cjs/src/helpers/areEqual.js +5 -0
- package/dist/cjs/src/helpers/cli/ASTBuilder.js +54 -2
- package/dist/cjs/src/helpers/cli/ASTKyselyCodegenEnhancer.js +84 -0
- package/dist/cjs/src/helpers/cli/ASTSchemaBuilder.js +17 -1
- package/dist/cjs/src/helpers/cli/generateFactoryContent.js +16 -0
- package/dist/cjs/src/helpers/cloneDeepSafe.js +21 -10
- package/dist/cjs/src/helpers/customPgParsers.js +18 -1
- package/dist/cjs/src/helpers/db/normalizeDataForDb.js +81 -0
- package/dist/cjs/src/helpers/db/types/helpers.js +5 -0
- package/dist/cjs/src/helpers/db/types/isDatetimeOrDatetimeArrayColumn.js +2 -1
- package/dist/cjs/src/helpers/sortBy.js +7 -5
- package/dist/cjs/src/helpers/sqlAttributes.js +4 -53
- package/dist/cjs/src/helpers/stringCasing.js +6 -5
- package/dist/cjs/src/helpers/toSafeObject.js +17 -0
- package/dist/cjs/src/package-exports/errors.js +2 -0
- package/dist/cjs/src/package-exports/index.js +2 -0
- package/dist/cjs/src/serializer/SerializerRenderer.js +11 -11
- package/dist/cjs/src/types/clocktime.js +1 -0
- package/dist/cjs/src/utils/datetime/BaseClockTime.js +363 -0
- package/dist/cjs/src/utils/datetime/CalendarDate.js +110 -119
- package/dist/cjs/src/utils/datetime/ClockTime.js +173 -0
- package/dist/cjs/src/utils/datetime/ClockTimeTz.js +232 -0
- package/dist/cjs/src/utils/datetime/DateTime.js +327 -221
- package/dist/cjs/src/utils/datetime/helpers/isoTimeDecimalString.js +8 -4
- package/dist/cjs/src/utils/datetime/helpers/replaceISOMicroseconds.js +4 -1
- package/dist/esm/src/Dream.js +2 -40
- package/dist/esm/src/cli/index.js +4 -0
- package/dist/esm/src/dream/Query.js +14 -11
- package/dist/esm/src/dream/QueryDriver/Base.js +0 -14
- package/dist/esm/src/dream/QueryDriver/Kysely.js +86 -74
- package/dist/esm/src/dream/QueryDriver/Postgres.js +10 -2
- package/dist/esm/src/dream/internal/extractAssignableAssociationAttributes.js +9 -0
- package/dist/esm/src/errors/db/DataIncompatibleWithDatabaseField.js +1 -3
- package/dist/esm/src/helpers/areEqual.js +5 -0
- package/dist/esm/src/helpers/cli/ASTBuilder.js +54 -2
- package/dist/esm/src/helpers/cli/ASTKyselyCodegenEnhancer.js +84 -0
- package/dist/esm/src/helpers/cli/ASTSchemaBuilder.js +17 -1
- package/dist/esm/src/helpers/cli/generateFactoryContent.js +16 -0
- package/dist/esm/src/helpers/cloneDeepSafe.js +21 -10
- package/dist/esm/src/helpers/customPgParsers.js +18 -1
- package/dist/esm/src/helpers/db/normalizeDataForDb.js +81 -0
- package/dist/esm/src/helpers/db/types/helpers.js +5 -0
- package/dist/esm/src/helpers/db/types/isDatetimeOrDatetimeArrayColumn.js +2 -1
- package/dist/esm/src/helpers/sortBy.js +7 -5
- package/dist/esm/src/helpers/sqlAttributes.js +4 -53
- package/dist/esm/src/helpers/stringCasing.js +6 -5
- package/dist/esm/src/helpers/toSafeObject.js +17 -0
- package/dist/esm/src/package-exports/errors.js +2 -0
- package/dist/esm/src/package-exports/index.js +2 -0
- package/dist/esm/src/serializer/SerializerRenderer.js +11 -11
- package/dist/esm/src/types/clocktime.js +1 -0
- package/dist/esm/src/utils/datetime/BaseClockTime.js +363 -0
- package/dist/esm/src/utils/datetime/CalendarDate.js +110 -119
- package/dist/esm/src/utils/datetime/ClockTime.js +173 -0
- package/dist/esm/src/utils/datetime/ClockTimeTz.js +232 -0
- package/dist/esm/src/utils/datetime/DateTime.js +327 -221
- package/dist/esm/src/utils/datetime/helpers/isoTimeDecimalString.js +8 -4
- package/dist/esm/src/utils/datetime/helpers/replaceISOMicroseconds.js +4 -1
- package/dist/types/src/Dream.d.ts +29 -33
- package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +9 -10
- package/dist/types/src/dream/DreamInstanceTransactionBuilder.d.ts +16 -16
- package/dist/types/src/dream/LeftJoinLoadBuilder.d.ts +1 -1
- package/dist/types/src/dream/LoadBuilder.d.ts +1 -1
- package/dist/types/src/dream/Query.d.ts +16 -16
- package/dist/types/src/dream/QueryDriver/Base.d.ts +0 -1
- package/dist/types/src/dream/QueryDriver/Kysely.d.ts +1 -0
- package/dist/types/src/dream/internal/associations/associationQuery.d.ts +1 -1
- package/dist/types/src/dream/internal/associations/associationUpdateQuery.d.ts +1 -1
- package/dist/types/src/dream/internal/associations/destroyAssociation.d.ts +1 -1
- package/dist/types/src/dream/internal/associations/throughAssociationHasOptionsBesidesThroughAndSource.d.ts +4 -2
- package/dist/types/src/dream/internal/associations/undestroyAssociation.d.ts +1 -1
- package/dist/types/src/dream/internal/extractAssignableAssociationAttributes.d.ts +3 -0
- package/dist/types/src/dream/internal/similarity/SimilarityBuilder.d.ts +7 -7
- package/dist/types/src/errors/db/DataIncompatibleWithDatabaseField.d.ts +2 -7
- package/dist/types/src/helpers/cli/ASTBuilder.d.ts +31 -0
- package/dist/types/src/helpers/cli/ASTKyselyCodegenEnhancer.d.ts +13 -0
- package/dist/types/src/helpers/customPgParsers.d.ts +5 -0
- package/dist/types/src/helpers/db/normalizeDataForDb.d.ts +6 -0
- package/dist/types/src/helpers/db/types/helpers.d.ts +5 -0
- package/dist/types/src/helpers/sort.d.ts +2 -1
- package/dist/types/src/helpers/sortBy.d.ts +3 -0
- package/dist/types/src/helpers/toSafeObject.d.ts +8 -0
- package/dist/types/src/package-exports/errors.d.ts +2 -0
- package/dist/types/src/package-exports/index.d.ts +2 -0
- package/dist/types/src/package-exports/types.d.ts +2 -1
- package/dist/types/src/types/associations/shared.d.ts +15 -13
- package/dist/types/src/types/associations/shared.ts +81 -41
- package/dist/types/src/types/calendardate.d.ts +22 -1
- package/dist/types/src/types/calendardate.ts +33 -1
- package/dist/types/src/types/clocktime.d.ts +22 -0
- package/dist/types/src/types/clocktime.ts +59 -0
- package/dist/types/src/types/datetime.d.ts +13 -18
- package/dist/types/src/types/datetime.ts +18 -21
- package/dist/types/src/types/dream.d.ts +27 -13
- package/dist/types/src/types/dream.ts +40 -14
- package/dist/types/src/types/variadic.d.ts +10 -9
- package/dist/types/src/types/variadic.ts +30 -5
- package/dist/types/src/utils/datetime/BaseClockTime.d.ts +287 -0
- package/dist/types/src/utils/datetime/CalendarDate.d.ts +65 -47
- package/dist/types/src/utils/datetime/ClockTime.d.ts +138 -0
- package/dist/types/src/utils/datetime/ClockTimeTz.d.ts +194 -0
- package/dist/types/src/utils/datetime/DateTime.d.ts +169 -66
- package/dist/types/src/utils/datetime/helpers/isoTimeDecimalString.d.ts +3 -2
- package/dist/types/src/utils/datetime/helpers/replaceISOMicroseconds.d.ts +4 -2
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/db.DreamMigrationHelpers.html +9 -9
- package/docs/classes/db.KyselyQueryDriver.html +33 -34
- package/docs/classes/db.PostgresQueryDriver.html +34 -35
- package/docs/classes/db.QueryDriverBase.html +32 -33
- package/docs/classes/errors.CheckConstraintViolation.html +4 -6
- package/docs/classes/errors.ColumnOverflow.html +4 -6
- package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +4 -6
- package/docs/classes/errors.DataTypeColumnTypeMismatch.html +4 -6
- package/docs/classes/errors.GlobalNameNotSet.html +3 -3
- package/docs/classes/errors.InvalidCalendarDate.html +2 -2
- package/docs/classes/errors.InvalidClockTime.html +17 -0
- package/docs/classes/errors.InvalidClockTimeTz.html +17 -0
- package/docs/classes/errors.InvalidDateTime.html +2 -2
- package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
- package/docs/classes/errors.NonLoadedAssociation.html +3 -3
- package/docs/classes/errors.NotNullViolation.html +4 -6
- package/docs/classes/errors.RecordNotFound.html +3 -3
- package/docs/classes/errors.ValidationError.html +3 -3
- package/docs/classes/index.CalendarDate.html +80 -92
- package/docs/classes/index.ClockTime.html +232 -0
- package/docs/classes/index.ClockTimeTz.html +253 -0
- package/docs/classes/index.DateTime.html +176 -173
- package/docs/classes/index.Decorators.html +19 -19
- package/docs/classes/index.Dream.html +127 -127
- package/docs/classes/index.DreamApp.html +5 -5
- package/docs/classes/index.DreamTransaction.html +2 -2
- package/docs/classes/index.Env.html +2 -2
- package/docs/classes/index.Query.html +71 -71
- package/docs/classes/system.CliFileWriter.html +2 -2
- package/docs/classes/system.DreamBin.html +2 -2
- package/docs/classes/system.DreamCLI.html +5 -5
- package/docs/classes/system.DreamImporter.html +2 -2
- package/docs/classes/system.DreamLogos.html +2 -2
- package/docs/classes/system.DreamSerializerBuilder.html +8 -8
- package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
- package/docs/classes/system.PathHelpers.html +3 -3
- package/docs/classes/utils.Encrypt.html +2 -2
- package/docs/classes/utils.Range.html +2 -2
- package/docs/functions/db.closeAllDbConnections.html +1 -1
- package/docs/functions/db.dreamDbConnections.html +1 -1
- package/docs/functions/db.untypedDb.html +1 -1
- package/docs/functions/db.validateColumn.html +1 -1
- package/docs/functions/db.validateTable.html +1 -1
- package/docs/functions/errors.pgErrorType.html +1 -1
- package/docs/functions/index.DreamSerializer.html +1 -1
- package/docs/functions/index.ObjectSerializer.html +1 -1
- package/docs/functions/index.ReplicaSafe.html +1 -1
- package/docs/functions/index.STI.html +1 -1
- package/docs/functions/index.SoftDelete.html +1 -1
- package/docs/functions/utils.camelize.html +1 -1
- package/docs/functions/utils.capitalize.html +1 -1
- package/docs/functions/utils.cloneDeepSafe.html +1 -1
- package/docs/functions/utils.compact.html +1 -1
- package/docs/functions/utils.groupBy.html +1 -1
- package/docs/functions/utils.hyphenize.html +1 -1
- package/docs/functions/utils.intersection.html +1 -1
- package/docs/functions/utils.isEmpty.html +1 -1
- package/docs/functions/utils.normalizeUnicode.html +1 -1
- package/docs/functions/utils.pascalize.html +1 -1
- package/docs/functions/utils.percent.html +1 -1
- package/docs/functions/utils.range-1.html +1 -1
- package/docs/functions/utils.round.html +1 -1
- package/docs/functions/utils.sanitizeString.html +1 -1
- package/docs/functions/utils.snakeify.html +1 -1
- package/docs/functions/utils.sort.html +1 -1
- package/docs/functions/utils.sortBy.html +1 -1
- package/docs/functions/utils.sortObjectByKey.html +1 -1
- package/docs/functions/utils.sortObjectByValue.html +1 -1
- package/docs/functions/utils.uncapitalize.html +1 -1
- package/docs/functions/utils.uniq.html +1 -1
- package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
- package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
- package/docs/interfaces/types.BelongsToStatement.html +2 -2
- package/docs/interfaces/types.DecoratorContext.html +2 -2
- package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
- package/docs/interfaces/types.DreamAppOpts.html +2 -2
- package/docs/interfaces/types.DurationObject.html +5 -5
- package/docs/interfaces/types.EncryptOptions.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
- package/docs/modules/db.html +1 -1
- package/docs/modules/errors.html +3 -1
- package/docs/modules/index.html +3 -1
- package/docs/modules/openapi.html +1 -1
- package/docs/modules/system.html +1 -1
- package/docs/modules/types.html +3 -1
- package/docs/modules/utils.html +1 -1
- package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/openapi.OpenapiAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiFormats.html +1 -1
- package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionRef.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
- package/docs/types/openapi.OpenapiSchemaNull.html +1 -1
- package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaString.html +1 -1
- package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiTypeField.html +1 -1
- package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
- package/docs/types/types.CalendarDateDurationUnit.html +1 -1
- package/docs/types/types.CalendarDateObject.html +2 -0
- package/docs/types/types.Camelized.html +1 -1
- package/docs/types/types.ClockTimeObject.html +2 -0
- package/docs/types/types.DbConnectionType.html +1 -1
- package/docs/types/types.DbTypes.html +1 -1
- package/docs/types/types.DreamAssociationMetadata.html +1 -1
- package/docs/types/types.DreamAttributes.html +1 -1
- package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
- package/docs/types/types.DreamClassColumn.html +1 -1
- package/docs/types/types.DreamColumn.html +1 -1
- package/docs/types/types.DreamColumnNames.html +1 -1
- package/docs/types/types.DreamLogLevel.html +1 -1
- package/docs/types/types.DreamLogger.html +1 -1
- package/docs/types/types.DreamModelSerializerType.html +1 -1
- package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
- package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/types.DreamParamSafeAttributes.html +1 -1
- package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
- package/docs/types/types.DreamSerializable.html +1 -1
- package/docs/types/types.DreamSerializableArray.html +1 -1
- package/docs/types/types.DreamSerializerKey.html +1 -1
- package/docs/types/types.DreamSerializers.html +1 -1
- package/docs/types/types.DreamVirtualColumns.html +1 -1
- package/docs/types/types.DurationUnit.html +2 -4
- package/docs/types/types.EncryptAlgorithm.html +1 -1
- package/docs/types/types.HasManyStatement.html +1 -1
- package/docs/types/types.HasOneStatement.html +1 -1
- package/docs/types/types.Hyphenized.html +1 -1
- package/docs/types/types.Pascalized.html +1 -1
- package/docs/types/types.PrimaryKeyType.html +1 -1
- package/docs/types/types.RoundingPrecision.html +1 -1
- package/docs/types/types.SerializerCasing.html +1 -1
- package/docs/types/types.SimpleObjectSerializerType.html +1 -1
- package/docs/types/types.Snakeified.html +1 -1
- package/docs/types/types.StrictInterface.html +1 -1
- package/docs/types/types.UpdateableAssociationProperties.html +1 -1
- package/docs/types/types.UpdateableProperties.html +1 -1
- package/docs/types/types.ValidationType.html +1 -1
- package/docs/types/types.ViewModel.html +1 -1
- package/docs/types/types.ViewModelClass.html +1 -1
- package/docs/types/types.WeekdayName.html +1 -1
- package/docs/types/types.WhereStatementForDream.html +1 -1
- package/docs/types/types.WhereStatementForDreamClass.html +1 -1
- package/docs/variables/index.DreamConst.html +1 -1
- package/docs/variables/index.ops.html +1 -1
- package/docs/variables/openapi.openapiPrimitiveTypes-1.html +1 -1
- package/docs/variables/openapi.openapiShorthandPrimitiveTypes-1.html +1 -1
- package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
- package/docs/variables/system.primaryKeyTypes.html +1 -1
- package/package.json +2 -2
- package/dist/cjs/src/helpers/db/types/isDateOrDateArrayColumn.js +0 -3
- package/dist/cjs/src/helpers/db/types/isTextOrTextArrayColumn.js +0 -3
- package/dist/esm/src/helpers/db/types/isDateOrDateArrayColumn.js +0 -3
- package/dist/esm/src/helpers/db/types/isTextOrTextArrayColumn.js +0 -3
- package/dist/types/src/helpers/db/types/isDateOrDateArrayColumn.d.ts +0 -2
- package/dist/types/src/helpers/db/types/isTextOrTextArrayColumn.d.ts +0 -2
|
@@ -4,9 +4,17 @@ import { microsecondParts } from './helpers/microsecondParts.js';
|
|
|
4
4
|
import replaceISOMicroseconds from './helpers/replaceISOMicroseconds.js';
|
|
5
5
|
export const Settings = LuxonSettings;
|
|
6
6
|
Settings.throwOnInvalid = true;
|
|
7
|
+
export const BASE_DATE_OBJECT = {
|
|
8
|
+
year: 2000,
|
|
9
|
+
month: 1,
|
|
10
|
+
day: 1,
|
|
11
|
+
};
|
|
7
12
|
/**
|
|
8
13
|
* DateTime wraps Luxon DateTime with microsecond precision (0-999).
|
|
9
14
|
* The decimal part in ISO/SQL is 6 digits: first 3 = milliseconds, next 3 = microseconds.
|
|
15
|
+
*
|
|
16
|
+
* Full datetime output (toISO, toSQL) is normalized to UTC.
|
|
17
|
+
* Time-only output (toISOTime, toSQLTime) omits timezone offset by default.
|
|
10
18
|
*/
|
|
11
19
|
export class DateTime {
|
|
12
20
|
luxonDatetime;
|
|
@@ -87,9 +95,6 @@ export class DateTime {
|
|
|
87
95
|
get offset() {
|
|
88
96
|
return this.luxonDatetime.offset;
|
|
89
97
|
}
|
|
90
|
-
get isValid() {
|
|
91
|
-
return this.luxonDatetime.isValid;
|
|
92
|
-
}
|
|
93
98
|
get invalidReason() {
|
|
94
99
|
return this.luxonDatetime.invalidReason;
|
|
95
100
|
}
|
|
@@ -102,6 +107,9 @@ export class DateTime {
|
|
|
102
107
|
get zone() {
|
|
103
108
|
return this.luxonDatetime.zone;
|
|
104
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* @internal
|
|
112
|
+
*/
|
|
105
113
|
constructor(luxonDatetime, microseconds = 0) {
|
|
106
114
|
this.luxonDatetime = luxonDatetime;
|
|
107
115
|
this._microseconds = microseconds;
|
|
@@ -127,8 +135,8 @@ export class DateTime {
|
|
|
127
135
|
* const now = DateTime.now()
|
|
128
136
|
* ```
|
|
129
137
|
*/
|
|
130
|
-
static now() {
|
|
131
|
-
return new DateTime(LuxonDateTime.now(), 0);
|
|
138
|
+
static now({ zone = 'UTC' } = {}) {
|
|
139
|
+
return new DateTime(LuxonDateTime.now().setZone(zone), 0);
|
|
132
140
|
}
|
|
133
141
|
// Format presets for toLocaleString()
|
|
134
142
|
/**
|
|
@@ -353,18 +361,22 @@ export class DateTime {
|
|
|
353
361
|
}
|
|
354
362
|
static local(yearOrOpts, month, day, hour, minute, second, millisecond, microsecondOrOpts, opts) {
|
|
355
363
|
const isOpts = (v) => typeof v === 'object' && v !== null;
|
|
356
|
-
const { luxonDatetime, microseconds } = buildLocalOrUtcDateTime(yearOrOpts, month, day, hour, minute, second, millisecond, microsecondOrOpts, opts, isOpts, (y, m, d, h, mi, s, ms,
|
|
364
|
+
const { luxonDatetime, microseconds } = buildLocalOrUtcDateTime(yearOrOpts, month, day, hour, minute, second, millisecond, microsecondOrOpts, opts, isOpts, (y, m, d, h, mi, s, ms, opts) => LuxonDateTime.local(y, m, d, h, mi, s, ms, opts));
|
|
357
365
|
return new DateTime(luxonDatetime, microseconds);
|
|
358
366
|
}
|
|
359
|
-
static utc(yearOrOpts, month, day, hour, minute, second, millisecond, microsecondOrOpts,
|
|
367
|
+
static utc(yearOrOpts, month, day, hour, minute, second, millisecond, microsecondOrOpts, opts) {
|
|
360
368
|
const isOpts = (v) => typeof v === 'object' && v !== null;
|
|
361
|
-
const { luxonDatetime, microseconds } = buildLocalOrUtcDateTime(yearOrOpts, month, day, hour, minute, second, millisecond, microsecondOrOpts,
|
|
369
|
+
const { luxonDatetime, microseconds } = buildLocalOrUtcDateTime(yearOrOpts, month, day, hour, minute, second, millisecond, microsecondOrOpts, opts, isOpts, (y, m, d, h, mi, s, ms, opts) => LuxonDateTime.utc(y, m, d, h, mi, s, ms, opts));
|
|
362
370
|
return new DateTime(luxonDatetime, microseconds);
|
|
363
371
|
}
|
|
364
372
|
/**
|
|
365
373
|
* Create a DateTime from a JavaScript Date.
|
|
366
374
|
* @param date - A JavaScript Date instance
|
|
367
|
-
* @param
|
|
375
|
+
* @param opts - Optional configuration
|
|
376
|
+
* @param opts.zone - Timezone for the result (IANA timezone name or Zone object)
|
|
377
|
+
* @param opts.locale - Locale string (e.g., 'en-US', 'fr-FR')
|
|
378
|
+
* @param opts.numberingSystem - Numbering system (e.g., 'arab', 'beng')
|
|
379
|
+
* @param opts.outputCalendar - Calendar system (e.g., 'islamic', 'hebrew')
|
|
368
380
|
* @returns A DateTime representing the same instant
|
|
369
381
|
* @example
|
|
370
382
|
* ```ts
|
|
@@ -372,66 +384,94 @@ export class DateTime {
|
|
|
372
384
|
* DateTime.fromJSDate(new Date(), { zone: 'America/New_York' })
|
|
373
385
|
* ```
|
|
374
386
|
*/
|
|
375
|
-
static fromJSDate(date,
|
|
376
|
-
const luxonDatetime =
|
|
387
|
+
static fromJSDate(date, opts) {
|
|
388
|
+
const luxonDatetime = opts
|
|
377
389
|
? // @ts-expect-error - exactOptionalPropertyTypes incompatibility with Luxon types
|
|
378
|
-
LuxonDateTime.fromJSDate(date,
|
|
390
|
+
LuxonDateTime.fromJSDate(date, opts)
|
|
379
391
|
: LuxonDateTime.fromJSDate(date);
|
|
380
392
|
return new DateTime(luxonDatetime, 0);
|
|
381
393
|
}
|
|
382
394
|
/**
|
|
383
395
|
* Create a DateTime from epoch milliseconds.
|
|
384
|
-
* @param
|
|
385
|
-
* @param
|
|
396
|
+
* @param millisecondInput - Unix timestamp in milliseconds (fractional part becomes microseconds)
|
|
397
|
+
* @param opts - Optional configuration
|
|
398
|
+
* @param opts.zone - Timezone for the result (IANA timezone name or Zone object)
|
|
399
|
+
* @param opts.locale - Locale string (e.g., 'en-US', 'fr-FR')
|
|
400
|
+
* @param opts.numberingSystem - Numbering system (e.g., 'arab', 'beng')
|
|
401
|
+
* @param opts.outputCalendar - Calendar system (e.g., 'islamic', 'hebrew')
|
|
386
402
|
* @returns A DateTime for the given instant
|
|
387
403
|
* @example
|
|
388
404
|
* ```ts
|
|
389
405
|
* DateTime.fromMillis(1707234567890)
|
|
406
|
+
* DateTime.fromMillis(1707234567890.123) // .123 ms = 123 microseconds
|
|
407
|
+
* DateTime.fromMillis(1707234567890, { zone: 'America/New_York' })
|
|
390
408
|
* ```
|
|
391
409
|
*/
|
|
392
|
-
static fromMillis(
|
|
393
|
-
const
|
|
394
|
-
|
|
410
|
+
static fromMillis(millisecondInput, opts) {
|
|
411
|
+
const { milliseconds, microseconds } = microsecondParts(millisecondInput * 1000, {
|
|
412
|
+
errorIfNegative: false,
|
|
413
|
+
});
|
|
414
|
+
return new DateTime(LuxonDateTime.fromMillis(milliseconds, opts), microseconds);
|
|
395
415
|
}
|
|
396
416
|
/**
|
|
397
417
|
* Create a DateTime from epoch microseconds.
|
|
398
418
|
* @param microseconds - Unix timestamp in microseconds (milliseconds from quotient, microsecond from remainder)
|
|
399
|
-
* @param
|
|
419
|
+
* @param opts - Optional configuration
|
|
420
|
+
* @param opts.zone - Timezone for the result (IANA timezone name or Zone object)
|
|
421
|
+
* @param opts.locale - Locale string (e.g., 'en-US', 'fr-FR')
|
|
422
|
+
* @param opts.numberingSystem - Numbering system (e.g., 'arab', 'beng')
|
|
423
|
+
* @param opts.outputCalendar - Calendar system (e.g., 'islamic', 'hebrew')
|
|
400
424
|
* @returns A DateTime for the given instant
|
|
401
425
|
* @example
|
|
402
426
|
* ```ts
|
|
403
427
|
* DateTime.fromMicroseconds(1707234567890123)
|
|
428
|
+
* DateTime.fromMicroseconds(1707234567890123, { zone: 'America/New_York' })
|
|
404
429
|
* ```
|
|
405
430
|
*/
|
|
406
|
-
static fromMicroseconds(microsecondsInput,
|
|
431
|
+
static fromMicroseconds(microsecondsInput, opts) {
|
|
407
432
|
const { milliseconds, microseconds } = microsecondParts(microsecondsInput);
|
|
408
|
-
const luxonDatetime = LuxonDateTime.fromMillis(milliseconds,
|
|
433
|
+
const luxonDatetime = LuxonDateTime.fromMillis(milliseconds, opts);
|
|
409
434
|
return new DateTime(luxonDatetime, microseconds);
|
|
410
435
|
}
|
|
411
436
|
/**
|
|
412
437
|
* Create a DateTime from epoch seconds.
|
|
413
|
-
*
|
|
414
|
-
* @param
|
|
438
|
+
* Fractional seconds are converted to milliseconds and microseconds.
|
|
439
|
+
* @param seconds - Unix timestamp in seconds (fractional part becomes ms + µs)
|
|
440
|
+
* @param opts - Optional configuration
|
|
441
|
+
* @param opts.zone - Timezone for the result (IANA timezone name or Zone object)
|
|
442
|
+
* @param opts.locale - Locale string (e.g., 'en-US', 'fr-FR')
|
|
443
|
+
* @param opts.numberingSystem - Numbering system (e.g., 'arab', 'beng')
|
|
444
|
+
* @param opts.outputCalendar - Calendar system (e.g., 'islamic', 'hebrew')
|
|
415
445
|
* @returns A DateTime for the given instant
|
|
416
446
|
* @example
|
|
417
447
|
* ```ts
|
|
418
448
|
* DateTime.fromSeconds(1707234567)
|
|
449
|
+
* DateTime.fromSeconds(1707234567.123456) // .123456 seconds = 123ms + 456µs
|
|
450
|
+
* DateTime.fromSeconds(1707234567, { zone: 'America/New_York' })
|
|
419
451
|
* ```
|
|
420
452
|
*/
|
|
421
|
-
static fromSeconds(seconds,
|
|
422
|
-
|
|
423
|
-
|
|
453
|
+
static fromSeconds(seconds, opts) {
|
|
454
|
+
// Convert seconds to microseconds to preserve full precision
|
|
455
|
+
const totalMicroseconds = seconds * 1_000_000;
|
|
456
|
+
const { milliseconds, microseconds } = microsecondParts(totalMicroseconds, { errorIfNegative: false });
|
|
457
|
+
const luxonDatetime = LuxonDateTime.fromMillis(milliseconds, opts);
|
|
458
|
+
return new DateTime(luxonDatetime, microseconds);
|
|
424
459
|
}
|
|
425
460
|
/**
|
|
426
461
|
* Create a DateTime from an object with date/time units.
|
|
427
462
|
* Fractional milliseconds are converted to microseconds (e.g., 1.5 ms = 1 ms + 500 µs).
|
|
428
|
-
* @param obj - Object with year, month, day,
|
|
429
|
-
* @param opts - Optional
|
|
463
|
+
* @param obj - Object with year, month, day, hour, minute, second, millisecond, microsecond
|
|
464
|
+
* @param opts - Optional configuration
|
|
465
|
+
* @param opts.zone - Timezone for the datetime (IANA timezone name or Zone object)
|
|
466
|
+
* @param opts.locale - Locale string (e.g., 'en-US', 'fr-FR')
|
|
467
|
+
* @param opts.numberingSystem - Numbering system (e.g., 'arab', 'beng')
|
|
468
|
+
* @param opts.outputCalendar - Calendar system (e.g., 'islamic', 'hebrew')
|
|
430
469
|
* @returns A DateTime for the given components
|
|
431
470
|
* @example
|
|
432
471
|
* ```ts
|
|
433
472
|
* DateTime.fromObject({ year: 2017, month: 3, day: 12, hour: 5, minute: 45, microsecond: 123 })
|
|
434
473
|
* DateTime.fromObject({ year: 2017, month: 3, day: 12, millisecond: 1.5 }) // 1ms + 500µs
|
|
474
|
+
* DateTime.fromObject({ year: 2017, month: 3, day: 12 }, { zone: 'America/New_York' })
|
|
435
475
|
* ```
|
|
436
476
|
*/
|
|
437
477
|
static fromObject(obj, opts) {
|
|
@@ -446,39 +486,56 @@ export class DateTime {
|
|
|
446
486
|
adjustedMillisecond = wholeMilli;
|
|
447
487
|
}
|
|
448
488
|
const { milliseconds, microseconds } = microsecondParts(microsecondsTotal);
|
|
449
|
-
const luxonDatetime = wrapLuxonError(() => LuxonDateTime.fromObject({ ...rest, millisecond: adjustedMillisecond }, opts));
|
|
489
|
+
const luxonDatetime = wrapLuxonError(() => LuxonDateTime.fromObject({ ...rest, millisecond: adjustedMillisecond }, (opts?.zone ? opts : { zone: 'UTC', ...opts })));
|
|
450
490
|
return new DateTime(milliseconds > 0 ? luxonDatetime.plus({ milliseconds }) : luxonDatetime, microseconds);
|
|
451
491
|
}
|
|
452
492
|
/**
|
|
453
493
|
* Create a DateTime from an ISO 8601 string.
|
|
454
494
|
* @param text - ISO string (e.g. "2024-03-15T10:30:45.123456-05:00"); parses up to 6 fractional second digits
|
|
455
|
-
* @param opts - Optional
|
|
495
|
+
* @param opts - Optional configuration
|
|
496
|
+
* @param opts.zone - Timezone to interpret/convert the datetime in (defaults to UTC)
|
|
497
|
+
* @param opts.locale - Locale string (e.g., 'en-US', 'fr-FR')
|
|
498
|
+
* @param opts.numberingSystem - Numbering system (e.g., 'arab', 'beng')
|
|
499
|
+
* @param opts.outputCalendar - Calendar system (e.g., 'islamic', 'hebrew')
|
|
456
500
|
* @returns A DateTime for the parsed instant
|
|
457
501
|
* @example
|
|
458
502
|
* ```ts
|
|
459
503
|
* DateTime.fromISO('2024-03-15T10:30:45.123456-05:00')
|
|
504
|
+
* DateTime.fromISO('2024-03-15T10:30:45Z', { zone: 'America/New_York' })
|
|
460
505
|
* ```
|
|
461
506
|
*/
|
|
462
507
|
static fromISO(text, opts) {
|
|
463
508
|
const { microsecond } = parseFractionalPart(text);
|
|
464
509
|
const textForLuxon = toThreeDecimalFraction(text);
|
|
465
|
-
const
|
|
510
|
+
const hasTimezoneInString = hasIsoTimezoneInformation(textForLuxon);
|
|
511
|
+
const luxonOpts = opts?.zone
|
|
512
|
+
? opts
|
|
513
|
+
: hasTimezoneInString
|
|
514
|
+
? { setZone: true, ...opts }
|
|
515
|
+
: { zone: 'UTC', ...opts };
|
|
516
|
+
const luxonDatetime = wrapLuxonError(() => LuxonDateTime.fromISO(textForLuxon, luxonOpts));
|
|
466
517
|
return new DateTime(luxonDatetime, microsecond);
|
|
467
518
|
}
|
|
468
519
|
/**
|
|
469
520
|
* Create a DateTime from an SQL datetime string.
|
|
470
521
|
* @param text - SQL string (e.g. "2024-03-15 10:30:45.123456"); parses up to 6 fractional second digits
|
|
471
|
-
* @param opts - Optional
|
|
522
|
+
* @param opts - Optional configuration
|
|
523
|
+
* @param opts.zone - Timezone to interpret the datetime in (overrides timezone in string)
|
|
524
|
+
* @param opts.locale - Locale string (e.g., 'en-US', 'fr-FR')
|
|
525
|
+
* @param opts.numberingSystem - Numbering system (e.g., 'arab', 'beng')
|
|
526
|
+
* @param opts.outputCalendar - Calendar system (e.g., 'islamic', 'hebrew')
|
|
472
527
|
* @returns A DateTime for the parsed instant
|
|
473
528
|
* @example
|
|
474
529
|
* ```ts
|
|
475
530
|
* DateTime.fromSQL('2024-03-15 10:30:45.123456')
|
|
531
|
+
* DateTime.fromSQL('2024-03-15 10:30:45', { zone: 'America/New_York' })
|
|
476
532
|
* ```
|
|
477
533
|
*/
|
|
478
534
|
static fromSQL(text, opts) {
|
|
479
535
|
const { microsecond } = parseFractionalPart(text);
|
|
480
536
|
const textForLuxon = toThreeDecimalFraction(text);
|
|
481
|
-
const
|
|
537
|
+
const luxonOpts = opts?.zone ? opts : { zone: 'UTC', ...opts };
|
|
538
|
+
const luxonDatetime = wrapLuxonError(() => LuxonDateTime.fromSQL(textForLuxon, luxonOpts));
|
|
482
539
|
return new DateTime(luxonDatetime, microsecond);
|
|
483
540
|
}
|
|
484
541
|
/**
|
|
@@ -499,39 +556,34 @@ export class DateTime {
|
|
|
499
556
|
* ```
|
|
500
557
|
*/
|
|
501
558
|
static fromFormat(text, format, opts) {
|
|
502
|
-
// Check if format includes microsecond token ('u' or 'SSSSSS')
|
|
503
559
|
const hasMicrosecondToken = format.includes('.u') || format.includes('.SSSSSS');
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
// 'SSSSSS' -> 'SSS'
|
|
512
|
-
const formatForLuxon = format.replace(/\.u\b/, '.SSS').replace(/\.SSSSSS\b/, '.SSS');
|
|
513
|
-
// Truncate fractional part to 3 digits for Luxon
|
|
514
|
-
const textForLuxon = toThreeDecimalFraction(text);
|
|
515
|
-
const luxonDatetime = wrapLuxonError(() => LuxonDateTime.fromFormat(textForLuxon, formatForLuxon, opts));
|
|
516
|
-
return new DateTime(luxonDatetime, microsecond);
|
|
517
|
-
}
|
|
518
|
-
else {
|
|
519
|
-
// No microsecond token, use Luxon directly
|
|
520
|
-
const luxonDatetime = wrapLuxonError(() => LuxonDateTime.fromFormat(text, format, opts));
|
|
521
|
-
return new DateTime(luxonDatetime, 0);
|
|
522
|
-
}
|
|
560
|
+
const microsecond = hasMicrosecondToken ? parseFractionalPart(text).microsecond : 0;
|
|
561
|
+
const textForLuxon = hasMicrosecondToken ? toThreeDecimalFraction(text) : text;
|
|
562
|
+
const formatForLuxon = hasMicrosecondToken
|
|
563
|
+
? format.replace(/\.u\b/, '.SSS').replace(/\.SSSSSS\b/, '.SSS')
|
|
564
|
+
: format;
|
|
565
|
+
const luxonDatetime = wrapLuxonError(() => LuxonDateTime.fromFormat(textForLuxon, formatForLuxon, opts));
|
|
566
|
+
return new DateTime(luxonDatetime, microsecond);
|
|
523
567
|
}
|
|
524
568
|
/**
|
|
525
569
|
* Returns an ISO 8601 string with 6 fractional second digits (milliseconds + microseconds).
|
|
526
|
-
*
|
|
527
|
-
*
|
|
570
|
+
*
|
|
571
|
+
* Always converts to UTC before formatting (e.g., '2024-03-15T15:30:45.123456Z').
|
|
572
|
+
*
|
|
573
|
+
* @param opts - Optional format options
|
|
574
|
+
* @param opts.suppressMilliseconds - If true, omits fractional seconds when they are zero
|
|
575
|
+
* @param opts.suppressSeconds - If true, omits seconds when they are zero
|
|
576
|
+
* @param opts.includeOffset - If true, includes timezone offset
|
|
577
|
+
* @param opts.format - Format variant: 'basic' (compact) or 'extended' (default, with separators)
|
|
578
|
+
* @returns ISO string (e.g. "2024-03-15T10:30:45.123456-05:00" or "2024-03-15T10:30:45.123456Z")
|
|
528
579
|
* @example
|
|
529
580
|
* ```ts
|
|
530
|
-
* DateTime.fromISO('2024-03-15T10:30:45.123456').toISO()
|
|
581
|
+
* DateTime.fromISO('2024-03-15T10:30:45.123456').toISO() // Converts to UTC
|
|
531
582
|
* ```
|
|
532
583
|
*/
|
|
533
584
|
toISO(opts) {
|
|
534
|
-
|
|
585
|
+
const dt = this.toUTC();
|
|
586
|
+
return replaceISOMicroseconds(dt, dt.luxonDatetime.toISO(opts), opts);
|
|
535
587
|
}
|
|
536
588
|
/**
|
|
537
589
|
* Returns an ISO date string (date only, no time).
|
|
@@ -546,27 +598,44 @@ export class DateTime {
|
|
|
546
598
|
}
|
|
547
599
|
/**
|
|
548
600
|
* Returns the time portion in ISO format with 6 fractional second digits.
|
|
601
|
+
*
|
|
602
|
+
* Omits timezone offset by default (e.g., '10:30:45.123456').
|
|
603
|
+
*
|
|
549
604
|
* @param opts - Optional format options
|
|
550
|
-
* @
|
|
605
|
+
* @param opts.suppressMilliseconds - If true, omits fractional seconds when they are zero
|
|
606
|
+
* @param opts.suppressSeconds - If true, omits seconds when they are zero
|
|
607
|
+
* @param opts.includeOffset - If true, includes timezone offset
|
|
608
|
+
* @param opts.format - Format variant: 'basic' (compact) or 'extended' (default, with colons)
|
|
609
|
+
* @returns Time string (e.g. "10:30:45.123456" or "10:30:45.123456-05:00")
|
|
551
610
|
* @example
|
|
552
611
|
* ```ts
|
|
553
|
-
* DateTime.local(2017, 3, 12, 10, 30, 45, 123, 456).toISOTime()
|
|
612
|
+
* DateTime.local(2017, 3, 12, 10, 30, 45, 123, 456).toISOTime() // '10:30:45.123456'
|
|
554
613
|
* ```
|
|
555
614
|
*/
|
|
556
615
|
toISOTime(opts) {
|
|
557
|
-
return replaceISOMicroseconds(this, this.luxonDatetime.toISOTime(
|
|
616
|
+
return replaceISOMicroseconds(this, this.luxonDatetime.toISOTime({
|
|
617
|
+
includeOffset: false,
|
|
618
|
+
...opts,
|
|
619
|
+
}), opts);
|
|
558
620
|
}
|
|
559
621
|
/**
|
|
560
622
|
* Returns an SQL datetime string with 6 fractional second digits.
|
|
561
|
-
*
|
|
623
|
+
*
|
|
624
|
+
* Always converts to UTC before formatting (e.g., '2024-03-15 15:30:45.123456').
|
|
625
|
+
*
|
|
562
626
|
* @returns SQL string (e.g. "2024-03-15 10:30:45.123456")
|
|
563
627
|
* @example
|
|
564
628
|
* ```ts
|
|
565
|
-
* DateTime.local(2017, 3, 12, 10, 30, 45, 123, 456).toSQL()
|
|
629
|
+
* DateTime.local(2017, 3, 12, 10, 30, 45, 123, 456).toSQL() // Converts to UTC
|
|
566
630
|
* ```
|
|
567
631
|
*/
|
|
568
|
-
|
|
569
|
-
|
|
632
|
+
_toSQL;
|
|
633
|
+
toSQL() {
|
|
634
|
+
if (this._toSQL)
|
|
635
|
+
return this._toSQL;
|
|
636
|
+
const dt = this.toUTC();
|
|
637
|
+
this._toSQL = replaceISOMicroseconds(dt, dt.luxonDatetime.toSQL(), {});
|
|
638
|
+
return this._toSQL;
|
|
570
639
|
}
|
|
571
640
|
/**
|
|
572
641
|
* Returns an SQL date string (date only, no time).
|
|
@@ -581,15 +650,22 @@ export class DateTime {
|
|
|
581
650
|
}
|
|
582
651
|
/**
|
|
583
652
|
* Returns an SQL time string with 6 fractional second digits.
|
|
584
|
-
*
|
|
653
|
+
*
|
|
654
|
+
* Omits timezone offset by default.
|
|
655
|
+
*
|
|
656
|
+
* @param opts - Optional SQL time format options
|
|
657
|
+
* @param opts.includeOffset - If true, includes timezone offset
|
|
585
658
|
* @returns SQL time string (e.g. "10:30:45.123456")
|
|
586
659
|
* @example
|
|
587
660
|
* ```ts
|
|
588
|
-
* DateTime.local(2017, 3, 12, 10, 30, 45, 123, 456).toSQLTime()
|
|
661
|
+
* DateTime.local(2017, 3, 12, 10, 30, 45, 123, 456).toSQLTime() // '10:30:45.123456'
|
|
662
|
+
* DateTime.local(2017, 3, 12, 10, 30, 45, 123, 456).toSQLTime({ includeOffset: true }) // '10:30:45.123456 -04:00'
|
|
589
663
|
* ```
|
|
590
664
|
*/
|
|
591
|
-
toSQLTime(opts) {
|
|
592
|
-
return replaceISOMicroseconds(this, this.luxonDatetime.toSQLTime(
|
|
665
|
+
toSQLTime(opts = {}) {
|
|
666
|
+
return replaceISOMicroseconds(this, this.luxonDatetime.toSQLTime({
|
|
667
|
+
includeOffset: opts.includeOffset ?? false,
|
|
668
|
+
}), {});
|
|
593
669
|
}
|
|
594
670
|
/**
|
|
595
671
|
* Returns a JavaScript Date object.
|
|
@@ -603,21 +679,30 @@ export class DateTime {
|
|
|
603
679
|
return this.luxonDatetime.toJSDate();
|
|
604
680
|
}
|
|
605
681
|
/**
|
|
606
|
-
* Returns
|
|
607
|
-
*
|
|
608
|
-
*
|
|
682
|
+
* Returns an ISO 8601 string representation (for valueOf() operations).
|
|
683
|
+
*
|
|
684
|
+
* Converts to UTC before formatting.
|
|
685
|
+
*
|
|
686
|
+
* @returns ISO datetime string with microsecond precision
|
|
609
687
|
* @example
|
|
610
688
|
* ```ts
|
|
611
|
-
* DateTime.local(2017, 3, 12).valueOf()
|
|
612
|
-
* DateTime.fromISO('2026-02-07T09:03:44.123456Z').valueOf()
|
|
689
|
+
* DateTime.local(2017, 3, 12).valueOf() // Converts to UTC
|
|
690
|
+
* DateTime.fromISO('2026-02-07T09:03:44.123456Z').valueOf() // '2026-02-07T09:03:44.123456Z'
|
|
613
691
|
* ```
|
|
614
692
|
*/
|
|
693
|
+
_valueOf;
|
|
615
694
|
valueOf() {
|
|
616
|
-
|
|
695
|
+
if (this._valueOf)
|
|
696
|
+
return this._valueOf;
|
|
697
|
+
this._valueOf = this.toISO();
|
|
698
|
+
return this._valueOf;
|
|
617
699
|
}
|
|
618
700
|
/**
|
|
619
701
|
* Returns an ISO 8601 formatted string for JSON serialization.
|
|
620
702
|
* This ensures DateTime objects are properly serialized to ISO format.
|
|
703
|
+
*
|
|
704
|
+
* Converts to UTC before formatting.
|
|
705
|
+
*
|
|
621
706
|
* @returns ISO datetime string with microsecond precision
|
|
622
707
|
* @example
|
|
623
708
|
* ```ts
|
|
@@ -631,6 +716,9 @@ export class DateTime {
|
|
|
631
716
|
/**
|
|
632
717
|
* Returns an ISO 8601 formatted string representation.
|
|
633
718
|
* Alias for toISO().
|
|
719
|
+
*
|
|
720
|
+
* Converts to UTC before formatting.
|
|
721
|
+
*
|
|
634
722
|
* @returns ISO datetime string with microsecond precision
|
|
635
723
|
* @example
|
|
636
724
|
* ```ts
|
|
@@ -644,12 +732,17 @@ export class DateTime {
|
|
|
644
732
|
}
|
|
645
733
|
/**
|
|
646
734
|
* Returns a localized string representation.
|
|
647
|
-
* @param formatOpts -
|
|
648
|
-
* @param opts - Optional locale
|
|
735
|
+
* @param formatOpts - Intl.DateTimeFormat options for formatting
|
|
736
|
+
* @param opts - Optional locale configuration
|
|
737
|
+
* @param opts.locale - Locale string (e.g., 'en-US', 'fr-FR')
|
|
738
|
+
* @param opts.numberingSystem - Numbering system (e.g., 'arab', 'beng')
|
|
739
|
+
* @param opts.outputCalendar - Calendar system (e.g., 'islamic', 'hebrew')
|
|
649
740
|
* @returns Localized string
|
|
650
741
|
* @example
|
|
651
742
|
* ```ts
|
|
652
743
|
* DateTime.local(2017, 3, 12).toLocaleString()
|
|
744
|
+
* DateTime.local(2017, 3, 12).toLocaleString(DateTime.DATE_FULL)
|
|
745
|
+
* DateTime.local(2017, 3, 12).toLocaleString({ weekday: 'long' }, { locale: 'fr-FR' })
|
|
653
746
|
* ```
|
|
654
747
|
*/
|
|
655
748
|
toLocaleString(formatOpts, opts) {
|
|
@@ -673,7 +766,6 @@ export class DateTime {
|
|
|
673
766
|
// Check if format contains fractional second tokens (S)
|
|
674
767
|
const fractionalMatch = fmt.match(/S+/);
|
|
675
768
|
if (!fractionalMatch) {
|
|
676
|
-
// No fractional seconds, just use Luxon's toFormat
|
|
677
769
|
return this.luxonDatetime.toFormat(fmt, opts);
|
|
678
770
|
}
|
|
679
771
|
const tokenLength = fractionalMatch[0].length;
|
|
@@ -699,35 +791,10 @@ export class DateTime {
|
|
|
699
791
|
* ```
|
|
700
792
|
*/
|
|
701
793
|
plus(duration) {
|
|
702
|
-
const
|
|
703
|
-
const { microseconds: microsecondsToAdd = 0, millisecond, milliseconds, ...rest } = durationObj;
|
|
704
|
-
// Handle both millisecond and milliseconds (prefer milliseconds if both are present)
|
|
705
|
-
const millisecondsToAdd = milliseconds ?? millisecond;
|
|
706
|
-
let microsecondsAdjusted = microsecondsToAdd;
|
|
707
|
-
// Build the object to pass to Luxon
|
|
708
|
-
const luxonDuration = { ...rest };
|
|
709
|
-
// Always handle fractional milliseconds by converting to microseconds
|
|
710
|
-
if (millisecondsToAdd !== undefined) {
|
|
711
|
-
const wholeMilli = Math.floor(millisecondsToAdd);
|
|
712
|
-
const fractionalMilli = millisecondsToAdd - wholeMilli;
|
|
713
|
-
microsecondsAdjusted += Math.round(fractionalMilli * 1000);
|
|
714
|
-
if (milliseconds !== undefined) {
|
|
715
|
-
luxonDuration.milliseconds = wholeMilli;
|
|
716
|
-
}
|
|
717
|
-
else {
|
|
718
|
-
luxonDuration.millisecond = wholeMilli;
|
|
719
|
-
}
|
|
720
|
-
}
|
|
794
|
+
const { luxonDuration, microsecondDelta } = splitDurationAndMicroseconds(duration);
|
|
721
795
|
const luxonDatetime = this.luxonDatetime.plus(luxonDuration);
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
const totalMicroseconds = this.microsecond + microsecondsAdjusted;
|
|
725
|
-
// Normalize the microseconds
|
|
726
|
-
const millisecondAdjustment = Math.floor(totalMicroseconds / 1000);
|
|
727
|
-
const finalMicroseconds = ((totalMicroseconds % 1000) + 1000) % 1000; // Ensure 0-999 range
|
|
728
|
-
return new DateTime(millisecondAdjustment !== 0
|
|
729
|
-
? luxonDatetime.plus({ milliseconds: millisecondAdjustment })
|
|
730
|
-
: luxonDatetime, finalMicroseconds);
|
|
796
|
+
const normalized = normalizeMicrosecondTotal(this.microsecond + microsecondDelta);
|
|
797
|
+
return new DateTime(applyMillisecondAdjustment(luxonDatetime, normalized.millisecondAdjustment), normalized.microseconds);
|
|
731
798
|
}
|
|
732
799
|
/**
|
|
733
800
|
* Subtracts a duration from this DateTime. Supports microsecond via DurationLikeObject.
|
|
@@ -741,34 +808,10 @@ export class DateTime {
|
|
|
741
808
|
* ```
|
|
742
809
|
*/
|
|
743
810
|
minus(duration) {
|
|
744
|
-
const
|
|
745
|
-
const { microseconds: microsecondsToSubtract = 0, millisecond, milliseconds, ...rest } = durationObj;
|
|
746
|
-
// Handle both millisecond and milliseconds (prefer milliseconds if both are present)
|
|
747
|
-
const millisecondsToSubtract = milliseconds ?? millisecond;
|
|
748
|
-
let microsecondsAdjusted = microsecondsToSubtract;
|
|
749
|
-
// Build the object to pass to Luxon
|
|
750
|
-
const luxonDuration = { ...rest };
|
|
751
|
-
// Always handle fractional milliseconds by converting to microseconds
|
|
752
|
-
if (millisecondsToSubtract !== undefined) {
|
|
753
|
-
const wholeMilli = Math.floor(millisecondsToSubtract);
|
|
754
|
-
const fractionalMilli = millisecondsToSubtract - wholeMilli;
|
|
755
|
-
microsecondsAdjusted += Math.round(fractionalMilli * 1000);
|
|
756
|
-
if (milliseconds !== undefined) {
|
|
757
|
-
luxonDuration.milliseconds = wholeMilli;
|
|
758
|
-
}
|
|
759
|
-
else {
|
|
760
|
-
luxonDuration.millisecond = wholeMilli;
|
|
761
|
-
}
|
|
762
|
-
}
|
|
811
|
+
const { luxonDuration, microsecondDelta } = splitDurationAndMicroseconds(duration);
|
|
763
812
|
const luxonDatetime = this.luxonDatetime.minus(luxonDuration);
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
// Normalize the microseconds
|
|
767
|
-
const millisecondAdjustment = Math.floor(totalMicroseconds / 1000);
|
|
768
|
-
const finalMicroseconds = ((totalMicroseconds % 1000) + 1000) % 1000; // Ensure 0-999 range
|
|
769
|
-
return new DateTime(millisecondAdjustment !== 0
|
|
770
|
-
? luxonDatetime.plus({ milliseconds: millisecondAdjustment })
|
|
771
|
-
: luxonDatetime, finalMicroseconds);
|
|
813
|
+
const normalized = normalizeMicrosecondTotal(this.microsecond - microsecondDelta);
|
|
814
|
+
return new DateTime(applyMillisecondAdjustment(luxonDatetime, normalized.millisecondAdjustment), normalized.microseconds);
|
|
772
815
|
}
|
|
773
816
|
/**
|
|
774
817
|
* Returns a new DateTime with the given units set.
|
|
@@ -787,16 +830,24 @@ export class DateTime {
|
|
|
787
830
|
}
|
|
788
831
|
/**
|
|
789
832
|
* Returns an object with date/time components including microsecond.
|
|
790
|
-
* @param opts - Optional options (includeConfig for Luxon config)
|
|
791
833
|
* @returns Object with year, month, day, hour, minute, second, millisecond, microsecond
|
|
792
834
|
* @example
|
|
793
835
|
* ```ts
|
|
794
836
|
* DateTime.local(2017, 3, 12, 5, 45, 10, 123, 456).toObject()
|
|
795
837
|
* ```
|
|
796
838
|
*/
|
|
797
|
-
toObject(
|
|
798
|
-
const obj = this.luxonDatetime.toObject(
|
|
799
|
-
return {
|
|
839
|
+
toObject() {
|
|
840
|
+
const obj = this.luxonDatetime.toObject();
|
|
841
|
+
return {
|
|
842
|
+
year: obj.year,
|
|
843
|
+
month: obj.month,
|
|
844
|
+
day: obj.day,
|
|
845
|
+
hour: obj.hour,
|
|
846
|
+
minute: obj.minute,
|
|
847
|
+
second: obj.second,
|
|
848
|
+
millisecond: obj.millisecond,
|
|
849
|
+
microsecond: this.microsecond,
|
|
850
|
+
};
|
|
800
851
|
}
|
|
801
852
|
/**
|
|
802
853
|
* Returns true if this and other represent the same instant and microsecond.
|
|
@@ -808,9 +859,7 @@ export class DateTime {
|
|
|
808
859
|
* ```
|
|
809
860
|
*/
|
|
810
861
|
equals(other) {
|
|
811
|
-
|
|
812
|
-
return false;
|
|
813
|
-
return this.microsecond === other.microsecond;
|
|
862
|
+
return this.valueOf() === other.valueOf();
|
|
814
863
|
}
|
|
815
864
|
/**
|
|
816
865
|
* Returns the epoch time in milliseconds (toMillis * 1000 + millisecond).
|
|
@@ -853,20 +902,38 @@ export class DateTime {
|
|
|
853
902
|
return luxonSeconds + additionalMicroseconds;
|
|
854
903
|
}
|
|
855
904
|
/**
|
|
856
|
-
* Returns the epoch time in seconds as an integer
|
|
857
|
-
* Truncates any fractional seconds, returning only the whole seconds portion.
|
|
858
|
-
* Equivalent to Math.floor(toSeconds()).
|
|
859
|
-
* @returns Unix timestamp in seconds (integer only, no fractional part)
|
|
905
|
+
* Returns the epoch time in seconds as an integer, truncating any fractional part.
|
|
860
906
|
* @example
|
|
861
907
|
* ```ts
|
|
862
|
-
* DateTime.
|
|
863
|
-
* DateTime.fromISO('2026-02-07T09:03:44.
|
|
864
|
-
* DateTime.fromISO('2026-02-07T09:03:44.999999Z').toUnixInteger() // 1770455024 (not rounded up)
|
|
908
|
+
* DateTime.fromISO('2026-02-07T09:03:44.123456Z').unixIntegerSeconds // 1770455024
|
|
909
|
+
* DateTime.fromISO('2026-02-07T09:03:44.999999Z').unixIntegerSeconds // 1770455024 (not rounded up)
|
|
865
910
|
* ```
|
|
866
911
|
*/
|
|
867
|
-
|
|
912
|
+
get unixIntegerSeconds() {
|
|
868
913
|
return Math.floor(this.toSeconds());
|
|
869
914
|
}
|
|
915
|
+
/**
|
|
916
|
+
* Returns the epoch time in milliseconds as an integer, truncating any fractional part.
|
|
917
|
+
* @example
|
|
918
|
+
* ```ts
|
|
919
|
+
* DateTime.fromISO('2026-02-07T09:03:44.123456Z').unixIntegerMilliseconds // 1770455024123
|
|
920
|
+
* DateTime.fromISO('2026-02-07T09:03:44.123999Z').unixIntegerMilliseconds // 1770455024123 (not rounded up)
|
|
921
|
+
* ```
|
|
922
|
+
*/
|
|
923
|
+
get unixIntegerMilliseconds() {
|
|
924
|
+
return Math.floor(this.toMillis());
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Returns the epoch time in microseconds as an integer.
|
|
928
|
+
* Equivalent to `toMicroseconds()` since microseconds are always whole numbers.
|
|
929
|
+
* @example
|
|
930
|
+
* ```ts
|
|
931
|
+
* DateTime.fromISO('2026-02-07T09:03:44.123456Z').unixIntegerMicroseconds // 1770455024123456
|
|
932
|
+
* ```
|
|
933
|
+
*/
|
|
934
|
+
get unixIntegerMicroseconds() {
|
|
935
|
+
return this.toMicroseconds();
|
|
936
|
+
}
|
|
870
937
|
/**
|
|
871
938
|
* Returns the earliest DateTime from the given arguments.
|
|
872
939
|
* @param dateTimes - DateTimes to compare
|
|
@@ -879,7 +946,7 @@ export class DateTime {
|
|
|
879
946
|
static min(...dateTimes) {
|
|
880
947
|
if (dateTimes.length === 0)
|
|
881
948
|
return null;
|
|
882
|
-
return dateTimes.reduce((
|
|
949
|
+
return dateTimes.reduce((min, datetime) => (datetime.valueOf() < min.valueOf() ? datetime : min), dateTimes[0]);
|
|
883
950
|
}
|
|
884
951
|
/**
|
|
885
952
|
* Returns the latest DateTime from the given arguments.
|
|
@@ -893,7 +960,7 @@ export class DateTime {
|
|
|
893
960
|
static max(...dateTimes) {
|
|
894
961
|
if (dateTimes.length === 0)
|
|
895
962
|
return null;
|
|
896
|
-
return dateTimes.reduce((
|
|
963
|
+
return dateTimes.reduce((max, datetime) => (datetime.valueOf() > max.valueOf() ? datetime : max), dateTimes[0]);
|
|
897
964
|
}
|
|
898
965
|
/**
|
|
899
966
|
* Returns a new DateTime in the given zone. Microsecond is preserved.
|
|
@@ -932,8 +999,7 @@ export class DateTime {
|
|
|
932
999
|
* ```
|
|
933
1000
|
*/
|
|
934
1001
|
toLocal() {
|
|
935
|
-
|
|
936
|
-
return new DateTime(luxonDatetime, this.microsecond);
|
|
1002
|
+
return new DateTime(this.luxonDatetime.toLocal(), this.microsecond);
|
|
937
1003
|
}
|
|
938
1004
|
/**
|
|
939
1005
|
* Returns a new DateTime at the start of the given unit.
|
|
@@ -1021,62 +1087,47 @@ export class DateTime {
|
|
|
1021
1087
|
* dt1.diff(dt2, 'days') // { days: 5 }
|
|
1022
1088
|
* dt1.diff(dt2, ['days', 'hours']) // { days: 5, hours: 3 }
|
|
1023
1089
|
* dt1.diff(dt2, ['milliseconds', 'microseconds']) // { milliseconds: 123, microseconds: 456 }
|
|
1024
|
-
* dt1.diff(dt2) // { years: 0, months: 0,
|
|
1090
|
+
* dt1.diff(dt2) // { years: 0, months: 0, days: 0, hours: 0, minutes: 0, seconds: 1, milliseconds: 500, microseconds: 0 }
|
|
1025
1091
|
* ```
|
|
1026
1092
|
*/
|
|
1027
1093
|
diff(other, unit) {
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
(
|
|
1034
|
-
|
|
1035
|
-
let luxonUnits = unit;
|
|
1036
|
-
if (Array.isArray(unit)) {
|
|
1037
|
-
const filtered = unit.filter(u => u !== 'microseconds');
|
|
1038
|
-
luxonUnits = filtered.length > 0 ? filtered : undefined;
|
|
1094
|
+
const unitArray = normalizeDiffUnitArray(unit);
|
|
1095
|
+
let result = {};
|
|
1096
|
+
const onlyMicroseconds = unitArray.length === 1 && unitArray[0] === 'microseconds';
|
|
1097
|
+
if (!onlyMicroseconds) {
|
|
1098
|
+
const luxonUnitArray = normalizeDiffUnitArray(unitArray.filter(u => u !== 'microseconds'));
|
|
1099
|
+
const luxonDuration = this.luxonDatetime.diff(other.toLuxon(), luxonUnitArray);
|
|
1100
|
+
result = luxonDuration.toObject();
|
|
1039
1101
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
const fullObject = luxonDuration.toObject();
|
|
1046
|
-
// Calculate microsecond difference if needed
|
|
1047
|
-
if (needsMicroseconds || unit === undefined) {
|
|
1048
|
-
// When microseconds is the ONLY unit requested, return total microseconds
|
|
1049
|
-
if (unit === 'microseconds') {
|
|
1050
|
-
const thisTotalMicroseconds = this.toMicroseconds();
|
|
1051
|
-
const otherTotalMicroseconds = other.toMicroseconds();
|
|
1052
|
-
fullObject.microseconds = thisTotalMicroseconds - otherTotalMicroseconds;
|
|
1102
|
+
const microsecondFieldDiff = this.microsecond - other.microsecond;
|
|
1103
|
+
if (unitArray.includes('microseconds')) {
|
|
1104
|
+
if (onlyMicroseconds) {
|
|
1105
|
+
const millisecondDiff = this.luxonDatetime.diff(other.toLuxon(), 'milliseconds').milliseconds ?? 0;
|
|
1106
|
+
result.microseconds = Math.round(millisecondDiff * 1000) + microsecondFieldDiff;
|
|
1053
1107
|
}
|
|
1054
1108
|
else {
|
|
1055
|
-
//
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1109
|
+
// Find the bottom (smallest) Luxon unit in the result and convert its
|
|
1110
|
+
// entire value to microseconds, add the microsecond field diff, then
|
|
1111
|
+
// split back. This handles borrowing/carrying automatically.
|
|
1112
|
+
const bottomUnit = bottomLuxonUnit(result);
|
|
1113
|
+
if (bottomUnit !== undefined) {
|
|
1114
|
+
const microsPerUnit = MICROSECONDS_PER_UNIT[bottomUnit];
|
|
1115
|
+
const totalMicros = Math.round(result[bottomUnit] * microsPerUnit) + microsecondFieldDiff;
|
|
1116
|
+
result[bottomUnit] = Math.trunc(totalMicros / microsPerUnit) || 0;
|
|
1117
|
+
result.microseconds = totalMicros - result[bottomUnit] * microsPerUnit;
|
|
1118
|
+
}
|
|
1119
|
+
else {
|
|
1120
|
+
result.microseconds = microsecondFieldDiff;
|
|
1121
|
+
}
|
|
1064
1122
|
}
|
|
1065
1123
|
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
return fullObject;
|
|
1069
|
-
}
|
|
1070
|
-
// If unit is a single string, return only that unit
|
|
1071
|
-
if (typeof unit === 'string') {
|
|
1072
|
-
return { [unit]: fullObject[unit] ?? 0 };
|
|
1124
|
+
else if (unitArray.includes('milliseconds')) {
|
|
1125
|
+
result.milliseconds = (result.milliseconds ?? 0) + microsecondFieldDiff / 1000;
|
|
1073
1126
|
}
|
|
1074
|
-
|
|
1075
|
-
const
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
}
|
|
1079
|
-
return result;
|
|
1127
|
+
const filtered = {};
|
|
1128
|
+
for (const requestedUnit of unitArray)
|
|
1129
|
+
filtered[requestedUnit] = result[requestedUnit] ?? 0;
|
|
1130
|
+
return filtered;
|
|
1080
1131
|
}
|
|
1081
1132
|
/**
|
|
1082
1133
|
* Returns the difference between this DateTime and now.
|
|
@@ -1112,33 +1163,84 @@ function wrapLuxonError(fn) {
|
|
|
1112
1163
|
* @internal
|
|
1113
1164
|
*/
|
|
1114
1165
|
function buildLocalOrUtcDateTime(yearOrOpts, month, day, hour, minute, second, millisecond, microsecondOrOpts, opts, isOpts, factory) {
|
|
1115
|
-
const options = isOpts
|
|
1116
|
-
? opts
|
|
1117
|
-
: isOpts(microsecondOrOpts)
|
|
1118
|
-
? microsecondOrOpts
|
|
1119
|
-
: isOpts(millisecond)
|
|
1120
|
-
? millisecond
|
|
1121
|
-
: isOpts(second)
|
|
1122
|
-
? second
|
|
1123
|
-
: isOpts(minute)
|
|
1124
|
-
? minute
|
|
1125
|
-
: isOpts(hour)
|
|
1126
|
-
? hour
|
|
1127
|
-
: isOpts(day)
|
|
1128
|
-
? day
|
|
1129
|
-
: isOpts(month)
|
|
1130
|
-
? month
|
|
1131
|
-
: isOpts(yearOrOpts)
|
|
1132
|
-
? yearOrOpts
|
|
1133
|
-
: undefined;
|
|
1166
|
+
const options = firstOptionArg(isOpts, opts, microsecondOrOpts, millisecond, second, minute, hour, day, month, yearOrOpts);
|
|
1134
1167
|
const { milliseconds: millisecondPartOfMicroseconds, microseconds } = microsecondParts(typeof microsecondOrOpts === 'number' ? microsecondOrOpts : 0);
|
|
1135
|
-
const y =
|
|
1136
|
-
const m =
|
|
1137
|
-
const d =
|
|
1138
|
-
const ms = (
|
|
1139
|
-
const luxonDatetime = factory(y, m, d,
|
|
1168
|
+
const y = numericOrDefault(yearOrOpts, 0);
|
|
1169
|
+
const m = numericOrDefault(month, 1);
|
|
1170
|
+
const d = numericOrDefault(day, 1);
|
|
1171
|
+
const ms = numericOrDefault(millisecond, 0) + millisecondPartOfMicroseconds;
|
|
1172
|
+
const luxonDatetime = factory(y, m, d, numericOrDefault(hour, 0), numericOrDefault(minute, 0), numericOrDefault(second, 0), ms, options);
|
|
1140
1173
|
return { luxonDatetime, microseconds };
|
|
1141
1174
|
}
|
|
1175
|
+
function splitDurationAndMicroseconds(duration) {
|
|
1176
|
+
const durationObj = typeof duration === 'number' ? { milliseconds: duration } : duration;
|
|
1177
|
+
const { microsecond = 0, microseconds = 0, millisecond, milliseconds, ...rest } = durationObj;
|
|
1178
|
+
const luxonDuration = { ...rest };
|
|
1179
|
+
const millisecondInput = milliseconds ?? millisecond;
|
|
1180
|
+
let microsecondDelta = microsecond + microseconds;
|
|
1181
|
+
if (millisecondInput !== undefined) {
|
|
1182
|
+
const wholeMilliseconds = Math.floor(millisecondInput);
|
|
1183
|
+
const fractionalMilliseconds = millisecondInput - wholeMilliseconds;
|
|
1184
|
+
microsecondDelta += Math.round(fractionalMilliseconds * 1000);
|
|
1185
|
+
if (milliseconds !== undefined) {
|
|
1186
|
+
luxonDuration.milliseconds = wholeMilliseconds;
|
|
1187
|
+
}
|
|
1188
|
+
else {
|
|
1189
|
+
luxonDuration.millisecond = wholeMilliseconds;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
return { luxonDuration: luxonDuration, microsecondDelta };
|
|
1193
|
+
}
|
|
1194
|
+
function normalizeMicrosecondTotal(totalMicroseconds) {
|
|
1195
|
+
const millisecondAdjustment = Math.floor(totalMicroseconds / 1000);
|
|
1196
|
+
const microseconds = ((totalMicroseconds % 1000) + 1000) % 1000;
|
|
1197
|
+
return { millisecondAdjustment, microseconds };
|
|
1198
|
+
}
|
|
1199
|
+
function applyMillisecondAdjustment(datetime, milliseconds) {
|
|
1200
|
+
return milliseconds !== 0 ? datetime.plus({ milliseconds }) : datetime;
|
|
1201
|
+
}
|
|
1202
|
+
function normalizeDiffUnitArray(unit) {
|
|
1203
|
+
if (unit === undefined)
|
|
1204
|
+
return DEFAULT_DIFF_UNITS_WITH_MICROSECONDS;
|
|
1205
|
+
return typeof unit === 'string' ? [unit] : unit.length === 0 ? DEFAULT_DIFF_UNITS_WITH_MICROSECONDS : unit;
|
|
1206
|
+
}
|
|
1207
|
+
const DEFAULT_DIFF_UNITS_WITH_MICROSECONDS = [
|
|
1208
|
+
'years',
|
|
1209
|
+
'months',
|
|
1210
|
+
'days',
|
|
1211
|
+
'hours',
|
|
1212
|
+
'minutes',
|
|
1213
|
+
'seconds',
|
|
1214
|
+
'milliseconds',
|
|
1215
|
+
'microseconds',
|
|
1216
|
+
];
|
|
1217
|
+
/** Microseconds per Luxon unit, ordered from smallest to largest unit. */
|
|
1218
|
+
const MICROSECONDS_PER_UNIT = {
|
|
1219
|
+
milliseconds: 1_000,
|
|
1220
|
+
seconds: 1_000_000,
|
|
1221
|
+
minutes: 60_000_000,
|
|
1222
|
+
hours: 3_600_000_000,
|
|
1223
|
+
days: 86_400_000_000,
|
|
1224
|
+
weeks: 604_800_000_000,
|
|
1225
|
+
};
|
|
1226
|
+
/** Returns the smallest Luxon unit present in the result object (excluding microseconds). */
|
|
1227
|
+
function bottomLuxonUnit(result) {
|
|
1228
|
+
for (const unit of Object.keys(MICROSECONDS_PER_UNIT)) {
|
|
1229
|
+
if (result[unit] !== undefined)
|
|
1230
|
+
return unit;
|
|
1231
|
+
}
|
|
1232
|
+
return undefined;
|
|
1233
|
+
}
|
|
1234
|
+
function numericOrDefault(value, fallback) {
|
|
1235
|
+
return typeof value === 'number' ? value : fallback;
|
|
1236
|
+
}
|
|
1237
|
+
function firstOptionArg(isOpts, ...values) {
|
|
1238
|
+
for (const value of values) {
|
|
1239
|
+
if (isOpts(value))
|
|
1240
|
+
return value;
|
|
1241
|
+
}
|
|
1242
|
+
return undefined;
|
|
1243
|
+
}
|
|
1142
1244
|
/** Parse fractional part from ISO/SQL string: first 3 digits = ms, next 3 = µs */
|
|
1143
1245
|
function parseFractionalPart(str) {
|
|
1144
1246
|
const match = str.match(/\.(\d+)/);
|
|
@@ -1158,6 +1260,10 @@ function toThreeDecimalFraction(str) {
|
|
|
1158
1260
|
const frac = (match[1] ?? '').padEnd(3, '0').slice(0, 3);
|
|
1159
1261
|
return str.replace(/\.\d+/, '.' + frac);
|
|
1160
1262
|
}
|
|
1263
|
+
const ISO_TIMEZONE_SUFFIX_REGEX = /(Z|[+-]\d{2}(?::?\d{2})?)$/i;
|
|
1264
|
+
function hasIsoTimezoneInformation(str) {
|
|
1265
|
+
return ISO_TIMEZONE_SUFFIX_REGEX.test(str);
|
|
1266
|
+
}
|
|
1161
1267
|
/**
|
|
1162
1268
|
* Thrown when a DateTime is invalid (e.g. invalid input or Luxon error).
|
|
1163
1269
|
* @param error - The original error (available as cause)
|