Change:
Issue Type: <bBug</bDoes this issue occur when all extensions are disabled?: Yes Snippets with multiple references to time-based snippet variables (eg. , , ) are not guaranteed to resolve to the same values due to the passage of time during the resolving process. a snippet with with multiple references to the snippet. There is a chance that the first will resolve to a different value than the second . I would expect that VSCode would save the time at the start of the resolution process and use it for the resolution of all time-based snippet variables. This is a time-based issue, so it helps to slow your CPU with heavy load. For example, I ran across this issue while running Folding on my machine. I'll submit a PR momentarily to fix this. VS Code version: Code - Insiders 1.59.0-insider (Universal) (, 2021-07-13T09:15:26.467Z) OS version: Darwin x64 20.5.0 Restricted Mode: Yes <details<summarySystem Info</summary </detailsExtensions: none<details<summaryA/B Experiments</summary</details<!-- generated by issue reporter --

Discussion:
private static readonly monthNames = [nls.localize('January', "January"), nls.localize('February', "February"), nls.localize('March', "March"), nls.localize('April', "April"), nls.localize('May', "May"), nls.localize('June', "June"), nls.localize('July', "July"), nls.localize('August', "August"), nls.localize('September', "September"), nls.localize('October', "October"), nls.localize('November', "November"), nls.localize('December', "December")]; private static readonly monthNamesShort = [nls.localize('JanuaryShort', "Jan"), nls.localize('FebruaryShort', "Feb"), nls.localize('MarchShort', "Mar"), nls.localize('AprilShort', "Apr"), nls.localize('MayShort', "May"), nls.localize('JuneShort', "Jun"), nls.localize('JulyShort', "Jul"), nls.localize('AugustShort', "Aug"), nls.localize('SeptemberShort', "Sep"), nls.localize('OctoberShort', "Oct"), nls.localize('NovemberShort', "Nov"), nls.localize('DecemberShort', "Dec")]; <ins> constructor(private readonly _date: Date = new Date()) { // } </ins> resolve(variable: Variable): string | undefined { const { name } = variable; if (name === 'CURRENT_YEAR') { <del> return String(new Date().getFullYear()); </del> <ins> return String(this._date.getFullYear()); </ins> } else if (name === 'CURRENT_YEAR_SHORT') { <del> return String(new Date().getFullYear()).slice(-2); </del> <ins> return String(this._date.getFullYear()).slice(-2); </ins> } else if (name === 'CURRENT_MONTH') { <del> return String(new Date().getMonth().valueOf() + 1).padStart(2, '0'); </del> <ins> return String(this._date.getMonth().valueOf() + 1).padStart(2, '0'); </ins> } else if (name === 'CURRENT_DATE') { <del> return String(new Date().getDate().valueOf()).padStart(2, '0'); </del> <ins> return String(this._date.getDate().valueOf()).padStart(2, '0'); </ins> } else if (name === 'CURRENT_HOUR') { <del> return String(new Date().getHours().valueOf()).padStart(2, '0'); </del> <ins> return String(this._date.getHours().valueOf()).padStart(2, '0'); </ins> } else if (name === 'CURRENT_MINUTE') { <del> return String(new Date().getMinutes().valueOf()).padStart(2, '0'); </del> <ins> return String(this._date.getMinutes().valueOf()).padStart(2, '0'); </ins> } else if (name === 'CURRENT_SECOND') { <del> return String(new Date().getSeconds().valueOf()).padStart(2, '0'); </del> <ins> return String(this._date.getSeconds().valueOf()).padStart(2, '0'); </ins> } else if (name === 'CURRENT_DAY_NAME') { <del> return TimeBasedVariableResolver.dayNames[new Date().getDay()]; </del> <ins> return TimeBasedVariableResolver.dayNames[this._date.getDay()]; </ins> } else if (name === 'CURRENT_DAY_NAME_SHORT') { <del> return TimeBasedVariableResolver.dayNamesShort[new Date().getDay()]; </del> <ins> return TimeBasedVariableResolver.dayNamesShort[this._date.getDay()]; </ins> } else if (name === 'CURRENT_MONTH_NAME') { <del> return TimeBasedVariableResolver.monthNames[new Date().getMonth()]; </del> <ins> return TimeBasedVariableResolver.monthNames[this._date.getMonth()]; </ins> } else if (name === 'CURRENT_MONTH_NAME_SHORT') { <del> return TimeBasedVariableResolver.monthNamesShort[new Date().getMonth()]; </del> <ins> return TimeBasedVariableResolver.monthNamesShort[this._date.getMonth()]; </ins> } else if (name === 'CURRENT_SECONDS_UNIX') { <del> return String(Math.floor(Date.now() / 1000)); </del> <ins> return String(Math.floor(this._date.getTime() / 1000)); </ins> } return undefined;

import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; import { sep } from 'vs/base/common/path'; import { toWorkspaceFolders } from 'vs/platform/workspaces/common/workspaces'; <ins> import * as sinon from 'sinon'; </ins> suite('Snippet Variables Resolver', function () {

assertVariableResolve3(resolver, 'CURRENT_SECONDS_UNIX'); }); <ins> test('Time-based snippet variables resolve to the same values even as time progresses', async function () { const snippetText = ` $CURRENT_YEAR $CURRENT_YEAR_SHORT $CURRENT_MONTH $CURRENT_DATE $CURRENT_HOUR $CURRENT_MINUTE $CURRENT_SECOND $CURRENT_DAY_NAME $CURRENT_DAY_NAME_SHORT $CURRENT_MONTH_NAME $CURRENT_MONTH_NAME_SHORT $CURRENT_SECONDS_UNIX `; const clock = sinon.useFakeTimers(); try { const resolver = new TimeBasedVariableResolver; const firstResolve = new SnippetParser().parse(snippetText).resolveVariables(resolver); clock.tick((365 * 24 * 3600 * 1000) + (24 * 3600 * 1000) + (3661 * 1000));  // 1 year + 1 day + 1 hour + 1 minute + 1 second const secondResolve = new SnippetParser().parse(snippetText).resolveVariables(resolver); assert.strictEqual(firstResolve.toString(), secondResolve.toString(), `Time-based snippet variables resolved differently`); } finally { clock.restore(); } }); </ins> test('creating snippet - format-condition doesn't work #53617', function () { const snippet = new SnippetParser().parse('${TM_LINE_NUMBER/(10)/${1:?It is:It is not}/} line 10', true);