diff --git a/packages/core-utils/src/common/date.ts b/packages/core-utils/src/common/date.ts index 4cabeb93c..f2c0e49dc 100644 --- a/packages/core-utils/src/common/date.ts +++ b/packages/core-utils/src/common/date.ts @@ -45,21 +45,42 @@ function isLastWeek (d: Date) { // --------------------------------------------------------------------------- -export const timecodeRegexString = `((\\d+)[h:])?((\\d+)[m:])?((\\d+)s?)` +export const timecodeRegexString = `(\\d+[h:])?(\\d+[m:])?\\d+s?` function timeToInt (time: number | string) { if (!time) return 0 if (typeof time === 'number') return time - const reg = new RegExp(`^${timecodeRegexString}$`) + // Try with 00h00m00s format first + const reg = new RegExp(`^(\\d+h)?(\\d+m)?(\\d+)s?$`) const matches = time.match(reg) - if (!matches) return 0 - const hours = parseInt(matches[2] || '0', 10) - const minutes = parseInt(matches[4] || '0', 10) - const seconds = parseInt(matches[6] || '0', 10) + if (matches) { + const hours = parseInt(matches[1] || '0', 10) + const minutes = parseInt(matches[2] || '0', 10) + const seconds = parseInt(matches[3] || '0', 10) - return hours * 3600 + minutes * 60 + seconds + return hours * 3600 + minutes * 60 + seconds + } + + // ':' format fallback + const parts = time.split(':').reverse() + + const iMultiplier = { + 0: 1, + 1: 60, + 2: 3600 + } + + let result = 0 + for (let i = parts.length - 1; i >= 0; i--) { + const partInt = parseInt(parts[i], 10) + if (isNaN(partInt)) return 0 + + result += iMultiplier[i] * partInt + } + + return result } function secondsToTime (seconds: number, full = false, symbol?: string) { diff --git a/packages/tests/src/server-helpers/core-utils.ts b/packages/tests/src/server-helpers/core-utils.ts index 909d4caa4..d2b5b0512 100644 --- a/packages/tests/src/server-helpers/core-utils.ts +++ b/packages/tests/src/server-helpers/core-utils.ts @@ -3,13 +3,13 @@ import { expect } from 'chai' import snakeCase from 'lodash-es/snakeCase.js' import validator from 'validator' -import { getAverageTheoreticalBitrate, getMaxTheoreticalBitrate, parseChapters } from '@peertube/peertube-core-utils' +import { getAverageTheoreticalBitrate, getMaxTheoreticalBitrate, parseChapters, timeToInt } from '@peertube/peertube-core-utils' import { VideoResolution } from '@peertube/peertube-models' import { objectConverter, parseBytes, parseDurationToMs, parseSemVersion } from '@peertube/peertube-server/core/helpers/core-utils.js' describe('Parse Bytes', function () { - it('Should pass on valid value', async function () { + it('Should pass on valid value', function () { // just return it expect(parseBytes(-1024)).to.equal(-1024) expect(parseBytes(1024)).to.equal(1024) @@ -43,14 +43,14 @@ describe('Parse Bytes', function () { expect(parseBytes('1024TB 1024GB 1024MB')).to.equal(1127000492212224) }) - it('Should be invalid when given invalid value', async function () { + it('Should be invalid when given invalid value', function () { expect(parseBytes('6GB 1GB')).to.equal(6) }) }) describe('Parse duration', function () { - it('Should pass when given valid value', async function () { + it('Should pass when given valid value', function () { expect(parseDurationToMs(35)).to.equal(35) expect(parseDurationToMs(-35)).to.equal(-35) expect(parseDurationToMs('35 seconds')).to.equal(35 * 1000) @@ -59,14 +59,32 @@ describe('Parse duration', function () { expect(parseDurationToMs('35 hours')).to.equal(3600 * 35 * 1000) }) - it('Should be invalid when given invalid value', async function () { + it('Should be invalid when given invalid value', function () { expect(parseBytes('35m 5s')).to.equal(35) }) }) +describe('Time to int', function () { + + it('Should correctly parse time to int', function () { + expect(timeToInt(undefined)).to.equal(0) + expect(timeToInt('')).to.equal(0) + + expect(timeToInt('1h02')).to.equal(3602) + + expect(timeToInt('1:02')).to.equal(62) + expect(timeToInt('01:2')).to.equal(62) + + expect(timeToInt('02h02m03s')).to.equal(7323) + expect(timeToInt('2:02:3')).to.equal(7323) + + expect(timeToInt(3500)).to.equal(3500) + }) +}) + describe('Object', function () { - it('Should convert an object', async function () { + it('Should convert an object', function () { function keyConverter (k: string) { return snakeCase(k) }