Skip to content
This repository was archived by the owner on May 20, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4271,6 +4271,43 @@
"experimental"
]
},
"github.copilot.chat.advanced.context.timeFormat": {
"type": "string",
"default": "off",
"enum": [
"off",
"24h",
"12h"
],
"enumDescriptions": [
"Do not include current time",
"24-hour format (e.g., 23:06:32)",
"12-hour format (e.g., 11:06:32 PM)"
],
"markdownDescription": "%github.copilot.config.advanced.context.timeFormat%",
"tags": [
"advanced",
"experimental"
]
},
"github.copilot.chat.advanced.context.showWeekday": {
"type": "boolean",
"default": false,
"markdownDescription": "%github.copilot.config.advanced.context.showWeekday%",
"tags": [
"advanced",
"experimental"
]
},
"github.copilot.chat.advanced.context.showTimezone": {
"type": "boolean",
"default": false,
"markdownDescription": "%github.copilot.config.advanced.context.showTimezone%",
"tags": [
"advanced",
"experimental"
]
},
"github.copilot.chat.agent.omitFileAttachmentContents": {
"type": "boolean",
"default": false,
Expand Down
3 changes: 3 additions & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,9 @@
"github.copilot.config.inlineEdits.chatSessionContextProvider.enabled": "Enable chat session context provider for next edit suggestions.",
"github.copilot.config.codesearch.agent.enabled": "Enable code search capabilities in agent mode.",
"github.copilot.config.agent.temperature": "Temperature setting for agent mode requests.",
"github.copilot.config.advanced.context.timeFormat": "Include the current time in the date context provided to the model. Choose between 24-hour and 12-hour format, or disable.",
"github.copilot.config.advanced.context.showWeekday": "Include the day of the week in the date context provided to the model.",
"github.copilot.config.advanced.context.showTimezone": "Include the timezone offset (e.g., GMT+2) in the date context provided to the model. Only applies when `#github.copilot.chat.advanced.context.timeFormat#` is not \"off\".",
"github.copilot.config.agent.omitFileAttachmentContents": "Omit summarized file contents from file attachments in agent mode, to encourage the agent to properly read and explore.",
"github.copilot.config.agent.largeToolResultsToDisk.enabled": "When enabled, large tool results are written to disk instead of being included directly in the context, helping manage context window usage.",
"github.copilot.config.agent.largeToolResultsToDisk.thresholdBytes": "The size threshold in bytes above which tool results are written to disk. Only applies when largeToolResultsToDisk.enabled is true.",
Expand Down
49 changes: 49 additions & 0 deletions src/extension/prompts/common/currentDateContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';

/**
* Formats the current date/time context string for inclusion in prompts.
* Respects user settings for time, weekday, and timezone display.
*
* Default (all settings off): "The current date is May 3, 2026."
* With all settings on: "The current date is Sunday, May 3, 2026. The current time is 23:06:32 GMT+2."
* Timezone is always in GMT±N offset format for consistency across all regions.
*
* timeFormat values: "off" (default), "24h", "12h"
*/
export function formatCurrentDateContext(configurationService: IConfigurationService): string {
const now = new Date();
const parts: string[] = [];

parts.push('The current date is ');

if (configurationService.getConfig(ConfigKey.Advanced.ShowWeekday)) {
parts.push(now.toLocaleDateString('en-US', { weekday: 'long' }));
parts.push(', ');
}

parts.push(now.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }));
parts.push('.');

const timeFormat = configurationService.getConfig(ConfigKey.Advanced.TimeFormat);
if (timeFormat && timeFormat !== 'off') {
const hour12 = timeFormat === '12h';
const timeStr = now.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12 });
parts.push(` The current time is ${timeStr}`);

if (configurationService.getConfig(ConfigKey.Advanced.ShowTimezone)) {
const tz = new Intl.DateTimeFormat('en-US', { timeZoneName: 'shortOffset' }).formatToParts(now).find(p => p.type === 'timeZoneName')?.value;
if (tz) {
parts.push(` ${tz}`);
}
}

parts.push('.');
}

return parts.join('');
}
181 changes: 181 additions & 0 deletions src/extension/prompts/common/test/currentDateContext.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { formatCurrentDateContext } from '../currentDateContext';
import { ConfigKey, IConfigurationService } from '../../../../platform/configuration/common/configurationService';

function createMockConfigService(overrides: { timeFormat?: string; showWeekday?: boolean; showTimezone?: boolean } = {}): IConfigurationService {
return {
_serviceBrand: undefined,
getConfig(key: unknown) {
if (key === ConfigKey.Advanced.TimeFormat) { return overrides.timeFormat ?? 'off'; }
if (key === ConfigKey.Advanced.ShowWeekday) { return overrides.showWeekday ?? false; }
if (key === ConfigKey.Advanced.ShowTimezone) { return overrides.showTimezone ?? false; }
return undefined;
},
} as unknown as IConfigurationService;
}

describe('formatCurrentDateContext', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.stubEnv('TZ', 'UTC');
// Monday, June 15, 2026 14:30:45 UTC
vi.setSystemTime(new Date('2026-06-15T14:30:45.000Z'));
Comment on lines +23 to +27
});

afterEach(() => {
vi.useRealTimers();
vi.unstubAllEnvs();
});

it('returns date only by default (all settings off)', () => {
const result = formatCurrentDateContext(createMockConfigService());
expect(result).toBe('The current date is June 15, 2026.');
});

it('includes time in 24h format', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '24h' }));
expect(result).toBe('The current date is June 15, 2026. The current time is 14:30:45.');
});

it('includes time in 12h format', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '12h' }));
expect(result).toBe('The current date is June 15, 2026. The current time is 02:30:45 PM.');
});

it('includes weekday when showWeekday is enabled', () => {
const result = formatCurrentDateContext(createMockConfigService({ showWeekday: true }));
expect(result).toBe('The current date is Monday, June 15, 2026.');
});

it('includes timezone when both time and showTimezone are enabled', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '24h', showTimezone: true }));
expect(result).toBe('The current date is June 15, 2026. The current time is 14:30:45 GMT+0.');

Check failure on line 57 in src/extension/prompts/common/test/currentDateContext.spec.ts

View workflow job for this annotation

GitHub Actions / Test (Linux)

src/extension/prompts/common/test/currentDateContext.spec.ts > formatCurrentDateContext > includes timezone when both time and showTimezone are enabled

AssertionError: expected 'The current date is June 15, 2026. Th…' to be 'The current date is June 15, 2026. Th…' // Object.is equality Expected: "The current date is June 15, 2026. The current time is 14:30:45 GMT+0." Received: "The current date is June 15, 2026. The current time is 14:30:45 GMT." ❯ src/extension/prompts/common/test/currentDateContext.spec.ts:57:18

Check failure on line 57 in src/extension/prompts/common/test/currentDateContext.spec.ts

View workflow job for this annotation

GitHub Actions / Test (Windows)

src/extension/prompts/common/test/currentDateContext.spec.ts > formatCurrentDateContext > includes timezone when both time and showTimezone are enabled

AssertionError: expected 'The current date is June 15, 2026. Th…' to be 'The current date is June 15, 2026. Th…' // Object.is equality Expected: "The current date is June 15, 2026. The current time is 14:30:45 GMT+0." Received: "The current date is June 15, 2026. The current time is 14:30:45 GMT." ❯ src/extension/prompts/common/test/currentDateContext.spec.ts:57:18
});

it('does not include timezone when time is off', () => {
const result = formatCurrentDateContext(createMockConfigService({ showTimezone: true }));
expect(result).toBe('The current date is June 15, 2026.');
});

it('includes all parts when all settings are enabled (24h)', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '24h', showWeekday: true, showTimezone: true }));
expect(result).toBe('The current date is Monday, June 15, 2026. The current time is 14:30:45 GMT+0.');

Check failure on line 67 in src/extension/prompts/common/test/currentDateContext.spec.ts

View workflow job for this annotation

GitHub Actions / Test (Linux)

src/extension/prompts/common/test/currentDateContext.spec.ts > formatCurrentDateContext > includes all parts when all settings are enabled (24h)

AssertionError: expected 'The current date is Monday, June 15, …' to be 'The current date is Monday, June 15, …' // Object.is equality Expected: "The current date is Monday, June 15, 2026. The current time is 14:30:45 GMT+0." Received: "The current date is Monday, June 15, 2026. The current time is 14:30:45 GMT." ❯ src/extension/prompts/common/test/currentDateContext.spec.ts:67:18

Check failure on line 67 in src/extension/prompts/common/test/currentDateContext.spec.ts

View workflow job for this annotation

GitHub Actions / Test (Windows)

src/extension/prompts/common/test/currentDateContext.spec.ts > formatCurrentDateContext > includes all parts when all settings are enabled (24h)

AssertionError: expected 'The current date is Monday, June 15, …' to be 'The current date is Monday, June 15, …' // Object.is equality Expected: "The current date is Monday, June 15, 2026. The current time is 14:30:45 GMT+0." Received: "The current date is Monday, June 15, 2026. The current time is 14:30:45 GMT." ❯ src/extension/prompts/common/test/currentDateContext.spec.ts:67:18
});

it('includes all parts when all settings are enabled (12h)', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '12h', showWeekday: true, showTimezone: true }));
expect(result).toBe('The current date is Monday, June 15, 2026. The current time is 02:30:45 PM GMT+0.');

Check failure on line 72 in src/extension/prompts/common/test/currentDateContext.spec.ts

View workflow job for this annotation

GitHub Actions / Test (Linux)

src/extension/prompts/common/test/currentDateContext.spec.ts > formatCurrentDateContext > includes all parts when all settings are enabled (12h)

AssertionError: expected 'The current date is Monday, June 15, …' to be 'The current date is Monday, June 15, …' // Object.is equality Expected: "The current date is Monday, June 15, 2026. The current time is 02:30:45 PM GMT+0." Received: "The current date is Monday, June 15, 2026. The current time is 02:30:45 PM GMT." ❯ src/extension/prompts/common/test/currentDateContext.spec.ts:72:18

Check failure on line 72 in src/extension/prompts/common/test/currentDateContext.spec.ts

View workflow job for this annotation

GitHub Actions / Test (Windows)

src/extension/prompts/common/test/currentDateContext.spec.ts > formatCurrentDateContext > includes all parts when all settings are enabled (12h)

AssertionError: expected 'The current date is Monday, June 15, …' to be 'The current date is Monday, June 15, …' // Object.is equality Expected: "The current date is Monday, June 15, 2026. The current time is 02:30:45 PM GMT+0." Received: "The current date is Monday, June 15, 2026. The current time is 02:30:45 PM GMT." ❯ src/extension/prompts/common/test/currentDateContext.spec.ts:72:18
});

it('weekday + time without timezone', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '24h', showWeekday: true }));
expect(result).toBe('The current date is Monday, June 15, 2026. The current time is 14:30:45.');
});

it('treats unknown timeFormat values as 24h', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: 'garbage' as any }));
expect(result).toBe('The current date is June 15, 2026. The current time is 14:30:45.');
});
});

describe('formatCurrentDateContext (US Eastern timezone)', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.stubEnv('TZ', 'America/New_York');
vi.setSystemTime(new Date('2026-06-15T14:30:45.000Z'));
});

afterEach(() => {
vi.useRealTimers();
vi.unstubAllEnvs();
});

it('shows local time and GMT-4 timezone', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '24h', showTimezone: true }));
expect(result).toBe('The current date is June 15, 2026. The current time is 10:30:45 GMT-4.');
});

it('shows all parts in Eastern timezone', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '12h', showWeekday: true, showTimezone: true }));
expect(result).toBe('The current date is Monday, June 15, 2026. The current time is 10:30:45 AM GMT-4.');
});
});

describe('formatCurrentDateContext (Tokyo timezone)', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.stubEnv('TZ', 'Asia/Tokyo');
vi.setSystemTime(new Date('2026-06-15T14:30:45.000Z'));
});

afterEach(() => {
vi.useRealTimers();
vi.unstubAllEnvs();
});

it('shows local time in Tokyo timezone', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '24h', showTimezone: true }));
expect(result).toBe('The current date is June 15, 2026. The current time is 23:30:45 GMT+9.');
});
});

describe('formatCurrentDateContext (US Pacific winter — PST)', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.stubEnv('TZ', 'America/Los_Angeles');
// January = PST (no daylight saving)
vi.setSystemTime(new Date('2026-01-15T20:30:45.000Z'));
});

afterEach(() => {
vi.useRealTimers();
vi.unstubAllEnvs();
});

it('shows GMT-8 in LA winter', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '24h', showTimezone: true }));
expect(result).toBe('The current date is January 15, 2026. The current time is 12:30:45 GMT-8.');
});
});

describe('formatCurrentDateContext (India — non-whole-hour offset)', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.stubEnv('TZ', 'Asia/Kolkata');
vi.setSystemTime(new Date('2026-06-15T14:30:45.000Z'));
});

afterEach(() => {
vi.useRealTimers();
vi.unstubAllEnvs();
});

it('shows GMT+5:30 offset', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '24h', showTimezone: true }));
expect(result).toBe('The current date is June 15, 2026. The current time is 20:00:45 GMT+5:30.');
});
});

describe('formatCurrentDateContext (date rollover — UTC night → Tokyo next day)', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.stubEnv('TZ', 'Asia/Tokyo');
// UTC Sunday 23:30 → Tokyo Monday 08:30, date rolls to June 16
vi.setSystemTime(new Date('2026-06-15T23:30:45.000Z'));
});

afterEach(() => {
vi.useRealTimers();
vi.unstubAllEnvs();
});

it('shows correct local date and weekday after rollover', () => {
const result = formatCurrentDateContext(createMockConfigService({ timeFormat: '24h', showWeekday: true, showTimezone: true }));
expect(result).toBe('The current date is Tuesday, June 16, 2026. The current time is 08:30:45 GMT+9.');
});
});
7 changes: 4 additions & 3 deletions src/extension/prompts/node/agent/agentPrompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { ChatRequestEditedFileEvent, LanguageModelToolInformation, Notebook
import { sessionResourceToId } from '../../../../platform/chat/common/chatDebugFileLoggerService';
import { ChatLocation } from '../../../../platform/chat/common/commonTypes';
import { ConfigKey, IConfigurationService } from '../../../../platform/configuration/common/configurationService';
import { formatCurrentDateContext } from '../../common/currentDateContext';
import { ICustomInstructionsService } from '../../../../platform/customInstructions/common/customInstructionsService';
import { USE_SKILL_ADHERENCE_PROMPT_SETTING } from '../../../../platform/customInstructions/common/promptTypes';
import { CacheType } from '../../../../platform/endpoint/common/endpointTypes';
Expand Down Expand Up @@ -492,15 +493,15 @@ class UserOSPrompt extends PromptElement<BasePromptElementProps> {
class CurrentDatePrompt extends PromptElement<BasePromptElementProps> {
constructor(
props: BasePromptElementProps,
@IEnvService private readonly envService: IEnvService) {
@IEnvService private readonly envService: IEnvService,
@IConfigurationService private readonly configurationService: IConfigurationService) {
super(props);
}

async render(state: void, sizing: PromptSizing) {
const dateStr = new Date().toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' });
// Only include current date when not running simulations, since if we generate cache entries with the current date, the cache will be invalidated every day
return (
!this.envService.isSimulation() && <>The current date is {dateStr}.</>
!this.envService.isSimulation() && <>{formatCurrentDateContext(this.configurationService)}</>
);
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/platform/configuration/common/configurationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,9 @@ export namespace ConfigKey {
export const EditRecordingEnabled = defineAndMigrateSetting('chat.advanced.editRecording.enabled', 'chat.editRecording.enabled', false);
export const CodeSearchAgentEnabled = defineAndMigrateSetting<boolean | undefined>('chat.advanced.codesearch.agent.enabled', 'chat.codesearch.agent.enabled', true);
export const AgentTemperature = defineAndMigrateSetting<number | undefined>('chat.advanced.agent.temperature', 'chat.agent.temperature', undefined);
export const TimeFormat = defineSetting<'off' | '24h' | '12h'>('chat.advanced.context.timeFormat', ConfigType.Simple, 'off');
export const ShowWeekday = defineSetting<boolean>('chat.advanced.context.showWeekday', ConfigType.Simple, false);
export const ShowTimezone = defineSetting<boolean>('chat.advanced.context.showTimezone', ConfigType.Simple, false);
export const EnableUserPreferences = defineAndMigrateSetting<boolean>('chat.advanced.enableUserPreferences', 'chat.enableUserPreferences', false);
export const SummarizeAgentConversationHistoryThreshold = defineAndMigrateSetting<number | undefined>('chat.advanced.summarizeAgentConversationHistoryThreshold', 'chat.summarizeAgentConversationHistoryThreshold', undefined);
export const AgentHistorySummarizationMode = defineAndMigrateSetting<string | undefined>('chat.advanced.agentHistorySummarizationMode', 'chat.agentHistorySummarizationMode', undefined);
Expand Down
Loading