diff --git a/packages/@aws-cdk/aws-applicationautoscaling/lib/schedule.ts b/packages/@aws-cdk/aws-applicationautoscaling/lib/schedule.ts index 59c62f9a0f54b..96d1a0e8ff390 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/lib/schedule.ts +++ b/packages/@aws-cdk/aws-applicationautoscaling/lib/schedule.ts @@ -1,3 +1,5 @@ +import { Duration } from '@aws-cdk/cdk'; + /** * Schedule for scheduled scaling actions */ @@ -14,10 +16,15 @@ export abstract class Schedule { /** * Construct a schedule from an interval and a time unit */ - public static rate(interval: number, unit: TimeUnit): Schedule { - const unitStr = interval !== 1 ? `${unit}s` : unit; + public static rate(duration: Duration): Schedule { + if (duration.toSeconds() === 0) { + throw new Error('Duration cannot be 0'); + } - return new LiteralSchedule(`rate(${interval} ${unitStr})`); + let rate = maybeRate(duration.toDays({ integral: false }), 'day'); + if (rate === undefined) { rate = maybeRate(duration.toHours({ integral: false }), 'hour'); } + if (rate === undefined) { rate = makeRate(duration.toMinutes({ integral: true }), 'minute'); } + return new LiteralSchedule(rate); } /** @@ -56,26 +63,6 @@ export abstract class Schedule { } } -/** - * What unit to interpret the rate in - */ -export enum TimeUnit { - /** - * The rate is in minutes - */ - Minute = 'minute', - - /** - * The rate is in hours - */ - Hour = 'hour', - - /** - * The rate is in days - */ - Day = 'day' -} - /** * Options to configure a cron expression * @@ -154,4 +141,19 @@ function formatISO(date?: Date) { } return num; } +} + +/** + * Return the rate if the rate is whole number + */ +function maybeRate(interval: number, singular: string) { + if (interval === 0 || !Number.isInteger(interval)) { return undefined; } + return makeRate(interval, singular); +} + +/** + * Return 'rate(${interval} ${singular}(s))` for the interval + */ +function makeRate(interval: number, singular: string) { + return interval === 1 ? `rate(1 ${singular})` : `rate(${interval} ${singular}s)`; } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-applicationautoscaling/test/test.cron.ts b/packages/@aws-cdk/aws-applicationautoscaling/test/test.cron.ts index 7c4968267695e..9fcf4bf4ca3fa 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/test/test.cron.ts +++ b/packages/@aws-cdk/aws-applicationautoscaling/test/test.cron.ts @@ -1,3 +1,4 @@ +import { Duration } from '@aws-cdk/cdk'; import { Test } from 'nodeunit'; import appscaling = require('../lib'); @@ -10,5 +11,19 @@ export = { 'test utc cron, hour and minute'(test: Test) { test.equals(appscaling.Schedule.cron({ hour: '18', minute: '24' }).expressionString, 'cron(24 18 * * ? *)'); test.done(); - } + }, + + 'rate must be whole number of minutes'(test: Test) { + test.throws(() => { + appscaling.Schedule.rate(Duration.seconds(12345)); + }, /'12345 seconds' cannot be converted into a whole number of minutes/); + test.done(); + }, + + 'rate cannot be 0'(test: Test) { + test.throws(() => { + appscaling.Schedule.rate(Duration.days(0)); + }, /Duration cannot be 0/); + test.done(); + }, }; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-applicationautoscaling/test/test.scalable-target.ts b/packages/@aws-cdk/aws-applicationautoscaling/test/test.scalable-target.ts index 4c1df119a9e78..b1d2c8e750a71 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/test/test.scalable-target.ts +++ b/packages/@aws-cdk/aws-applicationautoscaling/test/test.scalable-target.ts @@ -1,5 +1,6 @@ import { expect, haveResource } from '@aws-cdk/assert'; import cdk = require('@aws-cdk/cdk'); +import { Duration } from '@aws-cdk/cdk'; import { Test } from 'nodeunit'; import appscaling = require('../lib'); import { createScalableTarget } from './util'; @@ -37,7 +38,7 @@ export = { // WHEN target.scaleOnSchedule('ScaleUp', { - schedule: appscaling.Schedule.rate(1, appscaling.TimeUnit.Minute), + schedule: appscaling.Schedule.rate(Duration.minutes(1)), maxCapacity: 50, minCapacity: 1, }); diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.lit.ts b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.lit.ts index 080e00e1919ee..d17daca0799d9 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.lit.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.lit.ts @@ -27,7 +27,7 @@ class EventStack extends cdk.Stack { memoryLimitMiB: 512, cpu: 1, environment: { name: 'TRIGGER', value: 'CloudWatch Events' }, - schedule: events.Schedule.rate(1, events.TimeUnit.Minute), + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); /// !hide } diff --git a/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-ec2-task.lit.ts b/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-ec2-task.lit.ts index 98245c87cc115..542a63e2af2f2 100644 --- a/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-ec2-task.lit.ts +++ b/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-ec2-task.lit.ts @@ -30,7 +30,7 @@ class EventStack extends cdk.Stack { // An Rule that describes the event trigger (in this case a scheduled run) const rule = new events.Rule(this, 'Rule', { - schedule: events.Schedule.rate(1, events.TimeUnit.Minute), + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); // Use EcsTask as the target of the Rule diff --git a/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-fargate-task.ts b/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-fargate-task.ts index e00c0bb5cd6d5..f807679e77dac 100644 --- a/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-fargate-task.ts +++ b/packages/@aws-cdk/aws-events-targets/test/ecs/integ.event-fargate-task.ts @@ -26,7 +26,7 @@ class EventStack extends cdk.Stack { // A rule that describes the event trigger (in this case a scheduled run) const rule = new events.Rule(this, 'Rule', { - schedule: events.Schedule.rate(1, events.TimeUnit.Minute), + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); // Use EcsTask as the target of the Rule diff --git a/packages/@aws-cdk/aws-events-targets/test/lambda/integ.events.ts b/packages/@aws-cdk/aws-events-targets/test/lambda/integ.events.ts index 44c0e12893f54..bf4e5f2f01877 100644 --- a/packages/@aws-cdk/aws-events-targets/test/lambda/integ.events.ts +++ b/packages/@aws-cdk/aws-events-targets/test/lambda/integ.events.ts @@ -14,12 +14,12 @@ const fn = new lambda.Function(stack, 'MyFunc', { }); const timer = new events.Rule(stack, 'Timer', { - schedule: events.Schedule.rate(1, events.TimeUnit.Minute), + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); timer.addTarget(new targets.LambdaFunction(fn)); const timer2 = new events.Rule(stack, 'Timer2', { - schedule: events.Schedule.rate(2, events.TimeUnit.Minute), + schedule: events.Schedule.rate(cdk.Duration.minutes(2)), }); timer2.addTarget(new targets.LambdaFunction(fn)); diff --git a/packages/@aws-cdk/aws-events-targets/test/lambda/lambda.test.ts b/packages/@aws-cdk/aws-events-targets/test/lambda/lambda.test.ts index 3f1dec6280d5f..f3a49b1a2f50a 100644 --- a/packages/@aws-cdk/aws-events-targets/test/lambda/lambda.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/lambda/lambda.test.ts @@ -9,10 +9,10 @@ test('use lambda as an event rule target', () => { const stack = new cdk.Stack(); const fn = newTestLambda(stack); const rule1 = new events.Rule(stack, 'Rule', { - schedule: events.Schedule.rate(1, events.TimeUnit.Minute), + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); const rule2 = new events.Rule(stack, 'Rule2', { - schedule: events.Schedule.rate(5, events.TimeUnit.Minute), + schedule: events.Schedule.rate(cdk.Duration.minutes(5)), }); // WHEN diff --git a/packages/@aws-cdk/aws-events-targets/test/sns/integ.sns-event-rule-target.ts b/packages/@aws-cdk/aws-events-targets/test/sns/integ.sns-event-rule-target.ts index 244d7d9aec39d..01e1ad0929812 100644 --- a/packages/@aws-cdk/aws-events-targets/test/sns/integ.sns-event-rule-target.ts +++ b/packages/@aws-cdk/aws-events-targets/test/sns/integ.sns-event-rule-target.ts @@ -16,7 +16,7 @@ const stack = new cdk.Stack(app, 'aws-cdk-sns-event-target'); const topic = new sns.Topic(stack, 'MyTopic'); const event = new events.Rule(stack, 'EveryMinute', { - schedule: events.Schedule.rate(1, events.TimeUnit.Minute), + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); const queue = new sqs.Queue(stack, 'MyQueue'); diff --git a/packages/@aws-cdk/aws-events-targets/test/sns/sns.test.ts b/packages/@aws-cdk/aws-events-targets/test/sns/sns.test.ts index 389cbe801b559..7fb36ff8d417c 100644 --- a/packages/@aws-cdk/aws-events-targets/test/sns/sns.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/sns/sns.test.ts @@ -1,7 +1,7 @@ import { expect, haveResource } from '@aws-cdk/assert'; import events = require('@aws-cdk/aws-events'); import sns = require('@aws-cdk/aws-sns'); -import { Stack } from '@aws-cdk/cdk'; +import { Duration, Stack } from '@aws-cdk/cdk'; import targets = require('../../lib'); test('sns topic as an event rule target', () => { @@ -9,7 +9,7 @@ test('sns topic as an event rule target', () => { const stack = new Stack(); const topic = new sns.Topic(stack, 'MyTopic'); const rule = new events.Rule(stack, 'MyRule', { - schedule: events.Schedule.rate(1, events.TimeUnit.Hour), + schedule: events.Schedule.rate(Duration.hours(1)), }); // WHEN @@ -52,7 +52,7 @@ test('multiple uses of a topic as a target results in a single policy statement' // WHEN for (let i = 0; i < 5; ++i) { const rule = new events.Rule(stack, `Rule${i}`, { - schedule: events.Schedule.rate(1, events.TimeUnit.Hour), + schedule: events.Schedule.rate(Duration.hours(1)), }); rule.addTarget(new targets.SnsTopic(topic)); } diff --git a/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.ts b/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.ts index 6a0f14cd63a10..a468df4954893 100644 --- a/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.ts +++ b/packages/@aws-cdk/aws-events-targets/test/sqs/integ.sqs-event-rule-target.ts @@ -13,7 +13,7 @@ const app = new cdk.App(); const stack = new cdk.Stack(app, 'aws-cdk-sqs-event-target'); const event = new events.Rule(stack, 'MyRule', { - schedule: events.Schedule.rate(1, events.TimeUnit.Minute), + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); const queue = new sqs.Queue(stack, 'MyQueue'); diff --git a/packages/@aws-cdk/aws-events-targets/test/sqs/sqs.test.ts b/packages/@aws-cdk/aws-events-targets/test/sqs/sqs.test.ts index 388cf21e60af9..1bc25c0163727 100644 --- a/packages/@aws-cdk/aws-events-targets/test/sqs/sqs.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/sqs/sqs.test.ts @@ -1,7 +1,7 @@ import { expect, haveResource } from '@aws-cdk/assert'; import events = require('@aws-cdk/aws-events'); import sqs = require('@aws-cdk/aws-sqs'); -import { Stack } from '@aws-cdk/cdk'; +import { Duration, Stack } from '@aws-cdk/cdk'; import targets = require('../../lib'); test('sns topic as an event rule target', () => { @@ -9,7 +9,7 @@ test('sns topic as an event rule target', () => { const stack = new Stack(); const queue = new sqs.Queue(stack, 'MyQueue'); const rule = new events.Rule(stack, 'MyRule', { - schedule: events.Schedule.rate(1, events.TimeUnit.Hour), + schedule: events.Schedule.rate(Duration.hours(1)), }); // WHEN @@ -75,7 +75,7 @@ test('multiple uses of a queue as a target results in multi policy statement bec // WHEN for (let i = 0; i < 2; ++i) { const rule = new events.Rule(stack, `Rule${i}`, { - schedule: events.Schedule.rate(1, events.TimeUnit.Hour), + schedule: events.Schedule.rate(Duration.hours(1)), }); rule.addTarget(new targets.SqsQueue(queue)); } diff --git a/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts b/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts index d9df7d354e1dc..f96132663acdc 100644 --- a/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts @@ -8,7 +8,7 @@ test('State machine can be used as Event Rule target', () => { // GIVEN const stack = new cdk.Stack(); const rule = new events.Rule(stack, 'Rule', { - schedule: events.Schedule.rate(1, events.TimeUnit.Minute), + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); const stateMachine = new sfn.StateMachine(stack, 'SM', { definition: new sfn.Wait(stack, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }) diff --git a/packages/@aws-cdk/aws-events/lib/schedule.ts b/packages/@aws-cdk/aws-events/lib/schedule.ts index 766c3a0bd91ec..dc55d776f1989 100644 --- a/packages/@aws-cdk/aws-events/lib/schedule.ts +++ b/packages/@aws-cdk/aws-events/lib/schedule.ts @@ -1,3 +1,5 @@ +import { Duration } from "@aws-cdk/cdk"; + /** * Schedule for scheduled event rules */ @@ -14,10 +16,15 @@ export abstract class Schedule { /** * Construct a schedule from an interval and a time unit */ - public static rate(interval: number, unit: TimeUnit): Schedule { - const unitStr = interval !== 1 ? `${unit}s` : unit; + public static rate(duration: Duration): Schedule { + if (duration.toSeconds() === 0) { + throw new Error('Duration cannot be 0'); + } - return new LiteralSchedule(`rate(${interval} ${unitStr})`); + let rate = maybeRate(duration.toDays({ integral: false }), 'day'); + if (rate === undefined) { rate = maybeRate(duration.toHours({ integral: false }), 'hour'); } + if (rate === undefined) { rate = makeRate(duration.toMinutes({ integral: true }), 'minute'); } + return new LiteralSchedule(rate); } /** @@ -129,4 +136,19 @@ class LiteralSchedule extends Schedule { function fallback(x: T | undefined, def: T): T { return x === undefined ? def : x; +} + +/** + * Return the rate if the rate is whole number + */ +function maybeRate(interval: number, singular: string) { + if (interval === 0 || !Number.isInteger(interval)) { return undefined; } + return makeRate(interval, singular); +} + +/** + * Return 'rate(${interval} ${singular}(s))` for the interval + */ +function makeRate(interval: number, singular: string) { + return interval === 1 ? `rate(1 ${singular})` : `rate(${interval} ${singular}s)`; } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-events/test/test.input.ts b/packages/@aws-cdk/aws-events/test/test.input.ts index e5034d6e6fe47..5a18d98ff6027 100644 --- a/packages/@aws-cdk/aws-events/test/test.input.ts +++ b/packages/@aws-cdk/aws-events/test/test.input.ts @@ -1,8 +1,8 @@ import { expect, haveResourceLike } from '@aws-cdk/assert'; import cdk = require('@aws-cdk/cdk'); -import { Stack } from '@aws-cdk/cdk'; +import { Duration, Stack } from '@aws-cdk/cdk'; import { Test } from 'nodeunit'; -import { IRuleTarget, RuleTargetInput, Schedule, TimeUnit } from '../lib'; +import { IRuleTarget, RuleTargetInput, Schedule } from '../lib'; import { Rule } from '../lib/rule'; export = { @@ -11,7 +11,7 @@ export = { // GIVEN const stack = new Stack(); const rule = new Rule(stack, 'Rule', { - schedule: Schedule.rate(1, TimeUnit.Minute), + schedule: Schedule.rate(Duration.minutes(1)), }); // WHEN @@ -34,7 +34,7 @@ export = { // GIVEN const stack = new Stack(); const rule = new Rule(stack, 'Rule', { - schedule: Schedule.rate(1, TimeUnit.Minute), + schedule: Schedule.rate(Duration.minutes(1)), }); // WHEN @@ -56,7 +56,7 @@ export = { // GIVEN const stack = new Stack(); const rule = new Rule(stack, 'Rule', { - schedule: Schedule.rate(1, TimeUnit.Minute), + schedule: Schedule.rate(Duration.minutes(1)), }); // WHEN @@ -78,7 +78,7 @@ export = { // GIVEN const stack = new Stack(); const rule = new Rule(stack, 'Rule', { - schedule: Schedule.rate(1, TimeUnit.Minute), + schedule: Schedule.rate(Duration.minutes(1)), }); const world = cdk.Lazy.stringValue({ produce: () => 'world' }); diff --git a/packages/@aws-cdk/aws-events/test/test.rule.ts b/packages/@aws-cdk/aws-events/test/test.rule.ts index 2b6f53cccad9e..70a4eaff37c43 100644 --- a/packages/@aws-cdk/aws-events/test/test.rule.ts +++ b/packages/@aws-cdk/aws-events/test/test.rule.ts @@ -4,7 +4,7 @@ import { ServicePrincipal } from '@aws-cdk/aws-iam'; import cdk = require('@aws-cdk/cdk'); import { Stack } from '@aws-cdk/cdk'; import { Test } from 'nodeunit'; -import { EventField, IRule, IRuleTarget, RuleTargetInput, Schedule, TimeUnit } from '../lib'; +import { EventField, IRule, IRuleTarget, RuleTargetInput, Schedule } from '../lib'; import { Rule } from '../lib/rule'; // tslint:disable:object-literal-key-quotes @@ -14,7 +14,7 @@ export = { const stack = new cdk.Stack(); new Rule(stack, 'MyRule', { - schedule: Schedule.rate(10, TimeUnit.Minute), + schedule: Schedule.rate(cdk.Duration.minutes(10)), }); expect(stack).toMatch({ @@ -38,7 +38,7 @@ export = { // WHEN new Rule(stack, 'MyRule', { ruleName: cdk.PhysicalName.of('PhysicalName'), - schedule: Schedule.rate(10, TimeUnit.Minute), + schedule: Schedule.rate(cdk.Duration.minutes(10)), }); // THEN @@ -174,7 +174,7 @@ export = { const rule = new Rule(stack, 'EventRule', { targets: [ t1 ], - schedule: Schedule.rate(5, TimeUnit.Minute), + schedule: Schedule.rate(cdk.Duration.minutes(5)), }); rule.addTarget(t2); @@ -216,7 +216,7 @@ export = { const stack = new cdk.Stack(); const rule = new Rule(stack, 'EventRule', { - schedule: Schedule.rate(1, TimeUnit.Minute), + schedule: Schedule.rate(cdk.Duration.minutes(1)), }); // a plain string should just be stringified (i.e. double quotes added and escaped) @@ -301,7 +301,7 @@ export = { const stack = new cdk.Stack(); const rule = new Rule(stack, 'EventRule', { - schedule: Schedule.rate(1, TimeUnit.Minute), + schedule: Schedule.rate(cdk.Duration.minutes(1)), }); const role = new iam.Role(stack, 'SomeRole', { diff --git a/packages/@aws-cdk/aws-events/test/test.schedule.ts b/packages/@aws-cdk/aws-events/test/test.schedule.ts index bb3bfabfde834..8297560278c14 100644 --- a/packages/@aws-cdk/aws-events/test/test.schedule.ts +++ b/packages/@aws-cdk/aws-events/test/test.schedule.ts @@ -1,3 +1,4 @@ +import { Duration } from '@aws-cdk/cdk'; import { Test } from 'nodeunit'; import events = require('../lib'); @@ -29,4 +30,18 @@ export = { }).expressionString); test.done(); }, + + 'rate must be whole number of minutes'(test: Test) { + test.throws(() => { + events.Schedule.rate(Duration.seconds(12345)); + }, /'12345 seconds' cannot be converted into a whole number of minutes/); + test.done(); + }, + + 'rate cannot be 0'(test: Test) { + test.throws(() => { + events.Schedule.rate(Duration.days(0)); + }, /Duration cannot be 0/); + test.done(); + }, }; diff --git a/packages/@aws-cdk/cdk/lib/duration.ts b/packages/@aws-cdk/cdk/lib/duration.ts index d9ba10c861373..4640fa33b399c 100644 --- a/packages/@aws-cdk/cdk/lib/duration.ts +++ b/packages/@aws-cdk/cdk/lib/duration.ts @@ -85,24 +85,28 @@ export class Duration { * @returns the value of this `Duration` expressed in Seconds. */ public toSeconds(opts: TimeConversionOptions = {}): number { - if (this.unit === TimeUnit.Seconds) { return this.amount; } - return _ensureIntegral(this.amount, this.unit.inSeconds, opts); + return convert(this.amount, this.unit, TimeUnit.Seconds, opts); } /** * @returns the value of this `Duration` expressed in Minutes. */ public toMinutes(opts: TimeConversionOptions = {}): number { - if (this.unit === TimeUnit.Minutes) { return this.amount; } - return _ensureIntegral(this.amount, this.unit.inMinutes, opts); + return convert(this.amount, this.unit, TimeUnit.Minutes, opts); + } + + /** + * @returns the value of this `Duration` expressed in Hours. + */ + public toHours(opts: TimeConversionOptions = {}): number { + return convert(this.amount, this.unit, TimeUnit.Hours, opts); } /** * @returns the value of this `Duration` expressed in Days. */ public toDays(opts: TimeConversionOptions = {}): number { - if (this.unit === TimeUnit.Days) { return this.amount; } - return _ensureIntegral(this.amount, this.unit.inDays, opts); + return convert(this.amount, this.unit, TimeUnit.Days, opts); } /** @@ -169,12 +173,7 @@ class TimeUnit { public static readonly Hours = new TimeUnit('hours', 3_600); public static readonly Days = new TimeUnit('days', 86_400); - public readonly inMinutes: number; - public readonly inDays: number; - private constructor(public readonly label: string, public readonly inSeconds: number) { - this.inMinutes = inSeconds / 60; - this.inDays = inSeconds / 86_400; } public toString() { @@ -182,13 +181,16 @@ class TimeUnit { } } -function _ensureIntegral(amount: number, multiplier: number, { integral = true }: TimeConversionOptions): number { +function convert(amount: number, fromUnit: TimeUnit, toUnit: TimeUnit, { integral = true }: TimeConversionOptions) { + if (fromUnit.inSeconds === toUnit.inSeconds) { return amount; } + const multiplier = fromUnit.inSeconds / toUnit.inSeconds; + if (Token.isUnresolved(amount)) { throw new Error(`Unable to perform time unit conversion on un-resolved token ${amount}.`); } const value = amount * multiplier; if (!Number.isInteger(value) && integral) { - throw new Error(`Required integral time unit conversion, but value ${value} is not integral.`); + throw new Error(`'${amount} ${fromUnit}' cannot be converted into a whole number of ${toUnit}.`); } return value; -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/cdk/test/test.duration.ts b/packages/@aws-cdk/cdk/test/test.duration.ts index a7c2a9c9b630d..fda0d586bcc78 100644 --- a/packages/@aws-cdk/cdk/test/test.duration.ts +++ b/packages/@aws-cdk/cdk/test/test.duration.ts @@ -25,7 +25,7 @@ export = nodeunit.testCase({ test.equal(duration.toSeconds(), 300); test.equal(duration.toMinutes(), 5); - test.throws(() => duration.toDays(), /Required integral time unit conversion, but value/); + test.throws(() => duration.toDays(), /'300 seconds' cannot be converted into a whole number of days/); floatEqual(test, duration.toDays({ integral: false }), 300 / 86_400); test.equal(Duration.seconds(60 * 60 * 24).toDays(), 1); @@ -38,7 +38,7 @@ export = nodeunit.testCase({ test.equal(duration.toSeconds(), 300); test.equal(duration.toMinutes(), 5); - test.throws(() => duration.toDays(), /Required integral time unit conversion, but value/); + test.throws(() => duration.toDays(), /'5 minutes' cannot be converted into a whole number of days/); floatEqual(test, duration.toDays({ integral: false }), 300 / 86_400); test.equal(Duration.minutes(60 * 24).toDays(), 1); @@ -51,7 +51,7 @@ export = nodeunit.testCase({ test.equal(duration.toSeconds(), 18_000); test.equal(duration.toMinutes(), 300); - test.throws(() => duration.toDays(), /Required integral time unit conversion, but value/); + test.throws(() => duration.toDays(), /'5 hours' cannot be converted into a whole number of days/); floatEqual(test, duration.toDays({ integral: false }), 5 / 24); test.equal(Duration.hours(24).toDays(), 1);