Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

community: timezone added as zoneinfo object in 365 toolkits #23581

Closed
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
https://learn.microsoft.com/en-us/graph/auth/
"""

import logging
from datetime import datetime as dt
from typing import Any, Dict, List, Optional, Type

Expand All @@ -13,6 +14,8 @@
from langchain_community.tools.office365.base import O365BaseTool
from langchain_community.tools.office365.utils import UTC_FORMAT, clean_body

logger = logging.getLogger(__name__)


class SearchEventsInput(BaseModel):
"""Input for SearchEmails Tool.
Expand All @@ -39,6 +42,13 @@ class SearchEventsInput(BaseModel):
" hours from Coordinated Universal Time (UTC)."
)
)
timezone: Optional[str] = Field(
default=None,
description="The timezone for the event should be provided in the following "
"format: 'America/New_York'. "
"For example, the zoneinfo for a +05:30 timezone offset is "
"'Asia/Kolkata'.",
)
max_results: int = Field(
default=10,
description="The maximum number of results to return.",
Expand Down Expand Up @@ -82,7 +92,20 @@ def _run(
truncate: bool = True,
run_manager: Optional[CallbackManagerForToolRun] = None,
truncate_limit: int = 150,
timezone: Optional[str] = None,
) -> List[Dict[str, Any]]:
if not timezone:
try:
import tzlocal
except ImportError:
logger.debug(
"'timezone' not set and 'tzlocal' is not installed so local "
"timezone cannot be inferred."
)
pass
else:
timezone = timezone or tzlocal.get_localzone()

# Get calendar object
schedule = self.account.schedule()
calendar = schedule.get_default_calendar()
Expand All @@ -91,6 +114,20 @@ def _run(
start_datetime_query = dt.strptime(start_datetime, UTC_FORMAT)
end_datetime_query = dt.strptime(end_datetime, UTC_FORMAT)

if timezone:
try:
from zoneinfo import ZoneInfo
except ImportError:
logger.debug("Cannot set timezone because 'zoneinfo' isn't installed.")
pass
else:
start_datetime_query = start_datetime_query.replace(
tzinfo=ZoneInfo(timezone)
)
end_datetime_query = end_datetime_query.replace(
tzinfo=ZoneInfo(timezone)
)

# Run the query
q = calendar.new_query("start").greater_equal(start_datetime_query)
q.chain("and").on_attribute("end").less_equal(end_datetime_query)
Expand Down Expand Up @@ -121,6 +158,7 @@ def _run(
output_event["modified_date"] = event.modified.astimezone(
time_zone
).strftime(UTC_FORMAT)
output_event["timezone"] = timezone

output_events.append(output_event)

Expand Down
34 changes: 34 additions & 0 deletions libs/community/langchain_community/tools/office365/send_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
https://learn.microsoft.com/en-us/graph/auth/
"""

import logging
from datetime import datetime as dt
from typing import List, Optional, Type

Expand All @@ -13,6 +14,8 @@
from langchain_community.tools.office365.base import O365BaseTool
from langchain_community.tools.office365.utils import UTC_FORMAT

logger = logging.getLogger(__name__)


class SendEventSchema(BaseModel):
"""Input for CreateEvent Tool."""
Expand Down Expand Up @@ -45,6 +48,13 @@ class SendEventSchema(BaseModel):
" 2023, at 10:30 AM in a time zone with a positive offset of 3 "
" hours from Coordinated Universal Time (UTC).",
)
timezone: Optional[str] = Field(
default=None,
description="The timezone for the event should be provided in the following "
"format: 'America/New_York'. "
"For example, the zoneinfo for a +05:30 timezone offset is "
"'Asia/Kolkata'.",
)


class O365SendEvent(O365BaseTool): # type: ignore[override, override]
Expand All @@ -63,8 +73,21 @@ def _run(
subject: str,
start_datetime: str,
end_datetime: str,
timezone: Optional[str] = None,
run_manager: Optional[CallbackManagerForToolRun] = None,
) -> str:
if not timezone:
try:
import tzlocal
except ImportError:
logger.debug(
"'timezone' not set and 'tzlocal' is not installed so local "
"timezone cannot be inferred."
)
pass
else:
timezone = timezone or tzlocal.get_localzone()

# Get calendar object
schedule = self.account.schedule()
calendar = schedule.get_default_calendar()
Expand All @@ -75,6 +98,17 @@ def _run(
event.subject = subject
event.start = dt.strptime(start_datetime, UTC_FORMAT)
event.end = dt.strptime(end_datetime, UTC_FORMAT)

if timezone:
try:
from zoneinfo import ZoneInfo
except ImportError:
logger.debug("Cannot set timezone because 'zoneinfo' isn't installed.")
pass
else:
event.start = event.start.replace(tzinfo=ZoneInfo(timezone))
event.end = event.end.replace(tzinfo=ZoneInfo(timezone))

for attendee in attendees:
event.attendees.add(attendee)

Expand Down