timezoneapscheduler

Setting timezone in AsyncIOScheduler


I'm in the Pacific timezone and I'm creating a discord bot to send a message at 8am in CENTRAL time.

import os
import discord
from discord.ext import commands
from dotenv import load_dotenv
from rich import print
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger


load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
intents = discord.Intents.default()
intents.members = True


bot = commands.Bot(command_prefix = '!', intents=intents)

# Will become the good morning message
async def gm():
    c = bot.get_channel(channel_id_removed) 
    await c.send("This will be the good morning message.")

@bot.event
async def on_ready():
    for guild in bot.guilds:
        print(
            f'{bot.user} is connected to the following guild:\n'
            f'\t{guild.name} (id: {guild.id})'
        )

    #initializing scheduler for time of day sending
    scheduler = AsyncIOScheduler()
    # Attempts to set the timezone
    # scheduler = AsyncIOScheduler(timezone='America/Chicago')
    # scheduler = AsyncIOScheduler({'apscheduler.timezone': 'America/Chicago'})
    # scheduler.configure(timezone='America/Chicago')

    # Set the time for sending
    scheduler.add_job(gm, CronTrigger(hour="6", minute="0", second="0")) 

    #starting the scheduler
    scheduler.start()


@bot.event
async def on_member_join(member):
    general_channel = None
    guild_joined = member.guild
    print(guild_joined)
    general_channel = discord.utils.get(guild_joined.channels, name='general')

    print(f'General Channel ID: {general_channel}')
    if general_channel:
        embed=discord.Embed(title="Welcome!",description=f"Welcome to The Dungeon {member.mention}!!")
        await general_channel.send(embed=embed)

bot.run(TOKEN)

Environment:

Windows 10
Python 3.10.4

APScheduler           3.9.1
pytz                  2022.1
pytz-deprecation-shim 0.1.0.post0
tzdata                2022.1
tzlocal               4.2

I'm just wondering if I'm doing something wrong? Or if what I'm trying to do simply isn't supported? It works if I use my local time so I know the function is ok.


Solution

  • You are using the asyncio scheduler but you're not running an asyncio event loop, so there is no way this could work. Copy/paste from the provided example:

    from datetime import datetime
    import asyncio
    import os
    
    from apscheduler.schedulers.asyncio import AsyncIOScheduler
    
    
    def tick():
        print('Tick! The time is: %s' % datetime.now())
    
    
    if __name__ == '__main__':
        scheduler = AsyncIOScheduler()
        scheduler.add_job(tick, 'interval', seconds=3)
        scheduler.start()
        print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
    
        # Execution will block here until Ctrl+C (Ctrl+Break on Windows) is pressed.
        try:
            asyncio.get_event_loop().run_forever()
        except (KeyboardInterrupt, SystemExit):
            pass
    

    The reason it is not working is because, while scheduler.start() instantiates an event loop as a side effect, it expects the loop to be run elsewhere so that the scheduler can do its work.