[GH-ISSUE #19] UpdateInterval does not work #4

Closed
opened 2026-09-04 00:45:55 +02:00 by Stone_Red · 5 comments
Owner

Originally created by @jerry-monitor on GitHub (Jun 25, 2026).
Original GitHub issue: https://github.com/Stone-Red-Code/DesktopMagic/issues/19

I copied the line

public override int UpdateInterval => 1000;

from the built-in plugin for Date and Time, but it does not update and remains static.

I asume this is correct for my own custom plugin:

namespace Customdatetime;

internal partial class CustomDateTimePlugin : Plugin { ... }

Any comments are welcome.

Thanks!

Originally created by @jerry-monitor on GitHub (Jun 25, 2026). Original GitHub issue: https://github.com/Stone-Red-Code/DesktopMagic/issues/19 I copied the line ```csharp public override int UpdateInterval => 1000; ``` from the built-in plugin for Date and Time, but it does not update and remains static. I asume this is correct for my own custom plugin: ```csharp namespace Customdatetime; internal partial class CustomDateTimePlugin : Plugin { ... } ``` Any comments are welcome. Thanks!
Author
Owner

@Stone-Red-Code commented on GitHub (Jun 25, 2026):

Hi there, are the other plugins working as expected? If so it's probably an issue with your plugin.
Can you post the full plugin code?

<!-- gh-comment-id:4797451583 --> @Stone-Red-Code commented on GitHub (Jun 25, 2026): Hi there, are the other plugins working as expected? If so it's probably an issue with your plugin. Can you post the full plugin code?
Author
Owner

@jerry-monitor commented on GitHub (Jun 25, 2026):

Thanks for the quick feedback. Here's my code:

using System.Drawing;
using System.Drawing.Text;
using System.Globalization;
using System.Text.RegularExpressions;
using DesktopMagic.Api;
using DesktopMagic.Api.Settings;

namespace Customdatetime;

internal partial class CustomDateTimePlugin : Plugin
{
    [Setting("custom-date-time-format", "Custom Date/Time Format")]
    private readonly TextBox customDateTimeFormat = new("wk %w | %ddd %yyyy-%mm-%dd | %HH:%II:%ss");

    private DateTime oldDateTime = DateTime.MinValue;
    private bool themeChanged;

    public override int UpdateInterval => 1000;

    public override Bitmap? Main()
    {
        if (oldDateTime.Date == DateTime.Now.Date && !themeChanged)
        {
            return null;
        }

        oldDateTime = DateTime.Now;
        themeChanged = false;

        var culture = CultureInfo.CurrentCulture;
        var dateTime = DateTime.Now;

        var date = FormatDateTime(dateTime, this.customDateTimeFormat.Value);

        using var font = new Font(Application.Theme.Font, 200);

        var bmp = new Bitmap(1, 1);
        bmp.SetResolution(100, 100);
        using var tmpGr = Graphics.FromImage(bmp);
        tmpGr.TextRenderingHint = TextRenderingHint.AntiAlias;

        var size = tmpGr.MeasureString(date, font);

        bmp = new Bitmap((int)size.Width, (int)size.Height);
        bmp.SetResolution(100, 100);

        using var gr = Graphics.FromImage(bmp);
        using var brush = new SolidBrush(Application.Theme.PrimaryColor);

        gr.TextRenderingHint = TextRenderingHint.AntiAlias;
        gr.DrawString(date, font, brush, 0, 0);

        return bmp;
    }

    public override void OnThemeChanged()
    {
        themeChanged = true;
    }

    public override void OnSettingsChanged()
    {
        themeChanged = true;
    }

    private static string FormatDateTime(DateTime value, string format, string? timeZoneId = null)
    {
        try
        {
            return FormatGeneric(value, format, timeZoneId, CultureInfo.CurrentCulture);
        }
        catch (Exception ex)
        {
            return "ERR: " + ex.Message;
        }
    }

    private static string FormatGeneric(
        DateTime date,
        string formatStr,
        string? timeZoneId = null,
        CultureInfo? locale = null
    ) {
        var timeZone = timeZoneId != null ? TimeZoneInfo.FindSystemTimeZoneById(timeZoneId) : TimeZoneInfo.Local;
        locale ??= CultureInfo.CurrentCulture;

        var tzDate = TimeZoneInfo.ConvertTime(date, timeZone);

        var replacements = new Dictionary<string, string>
        {
            ["%dateFull"] = tzDate.ToString("D", locale),
            ["%dateLong"] = tzDate.ToString("D", locale),
            ["%dateMedium"] = tzDate.ToString("d", locale), 
            ["%dateShort"] = tzDate.ToString("d", locale),
            ["%timeFull"] = tzDate.ToString("T", locale) + " " + (timeZone.IsDaylightSavingTime(tzDate) ? timeZone.DaylightName : timeZone.StandardName),
            ["%timeLong"] = tzDate.ToString("T", locale) + " " + (timeZone.IsDaylightSavingTime(tzDate) ? timeZone.DaylightName : timeZone.StandardName),
            ["%timeMedium"] = tzDate.ToString("T", locale),
            ["%timeShort"] = tzDate.ToString("t", locale),
            ["%dddd"] = tzDate.ToString("dddd", locale),
            ["%ddd"] = tzDate.ToString("ddd", locale),
            ["%yyyy"] = tzDate.ToString("yyyy", locale),
            ["%yy"] = tzDate.ToString("yy", locale),
            ["%y"] = tzDate.ToString("yyyy", locale),
            ["%Y"] = tzDate.ToString("yyyy", locale),
            ["%MMMM"] = tzDate.ToString("MMMM", locale),
            ["%MMM"] = tzDate.ToString("MMM", locale),
            ["%mm"] = tzDate.ToString("MM", locale),
            ["%m"] = tzDate.ToString("M", locale),
            ["%dd"] = tzDate.ToString("dd", locale),
            ["%d"] = tzDate.ToString("d", locale),
            ["%DDD"] = GetDayOfYearPadded(tzDate),
            ["%D"] = GetDayOfYear(tzDate),
            ["%hh"] = tzDate.ToString("hh", locale),
            ["%h"] = tzDate.ToString("%h", locale),
            ["%HH"] = tzDate.ToString("HH", locale),
            ["%H"] = tzDate.ToString("%H", locale),
            ["%ii"] = tzDate.ToString("mm", locale),
            ["%i"] = tzDate.ToString("%m", locale),
            ["%ss"] = tzDate.ToString("ss", locale),
            ["%s"] = tzDate.ToString("%s", locale),
            ["%SSS"] = tzDate.ToString("fff", locale),
            ["%S"] = tzDate.ToString("%f", locale),
            ["%a"] = GetAmPm(tzDate, locale),
            ["%A"] = GetAmPmUpper(tzDate, locale),
            ["%ww"] = GetIsoWeekPadded(tzDate),
            ["%w"] = GetIsoWeek(tzDate),
            ["%EE"] = tzDate.ToString("dddd", locale),
            ["%E"] = tzDate.ToString("ddd", locale),
            ["%e"] = ((int)tzDate.DayOfWeek).ToString(),
            ["%qq"] = GetQuarterPadded(tzDate),
            ["%q"] = GetQuarter(tzDate),
            ["%zz"] = timeZone.Id,
            ["%z"] = timeZone.IsDaylightSavingTime(tzDate) ? timeZone.DaylightName : timeZone.StandardName,
        };

        var formatRegex = string.Join("|", replacements.Keys);

        return Regex.Replace(
            formatStr,
            formatRegex,
            match => replacements.TryGetValue(match.Value, out var replacement) ? replacement : match.Value
        );

        string GetIsoWeek(DateTime d)
        {
            DayOfWeek day = locale.Calendar.GetDayOfWeek(d);
            if (day is >= DayOfWeek.Monday and <= DayOfWeek.Wednesday)
            {
                d = d.AddDays(3);
            }
            return locale.Calendar.GetWeekOfYear(d, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday).ToString();
        }

        string GetAmPmUpper(DateTime d, CultureInfo l) => d.ToString("tt", l).ToUpper();
        string GetAmPm(DateTime d, CultureInfo l) => d.ToString("tt", l).ToLower();
        string GetQuarterPadded(DateTime d) => GetQuarter(d).PadLeft(2, '0');
        string GetQuarter(DateTime d) => ((d.Month + 2) / 3).ToString();
        string GetIsoWeekPadded(DateTime d) => GetIsoWeek(d).PadLeft(2, '0');
        string GetDayOfYearPadded(DateTime d) => d.DayOfYear.ToString("D3");
        string GetDayOfYear(DateTime d) => d.DayOfYear.ToString();
    }
}

<!-- gh-comment-id:4798541687 --> @jerry-monitor commented on GitHub (Jun 25, 2026): Thanks for the quick feedback. Here's my code: ```csharp using System.Drawing; using System.Drawing.Text; using System.Globalization; using System.Text.RegularExpressions; using DesktopMagic.Api; using DesktopMagic.Api.Settings; namespace Customdatetime; internal partial class CustomDateTimePlugin : Plugin { [Setting("custom-date-time-format", "Custom Date/Time Format")] private readonly TextBox customDateTimeFormat = new("wk %w | %ddd %yyyy-%mm-%dd | %HH:%II:%ss"); private DateTime oldDateTime = DateTime.MinValue; private bool themeChanged; public override int UpdateInterval => 1000; public override Bitmap? Main() { if (oldDateTime.Date == DateTime.Now.Date && !themeChanged) { return null; } oldDateTime = DateTime.Now; themeChanged = false; var culture = CultureInfo.CurrentCulture; var dateTime = DateTime.Now; var date = FormatDateTime(dateTime, this.customDateTimeFormat.Value); using var font = new Font(Application.Theme.Font, 200); var bmp = new Bitmap(1, 1); bmp.SetResolution(100, 100); using var tmpGr = Graphics.FromImage(bmp); tmpGr.TextRenderingHint = TextRenderingHint.AntiAlias; var size = tmpGr.MeasureString(date, font); bmp = new Bitmap((int)size.Width, (int)size.Height); bmp.SetResolution(100, 100); using var gr = Graphics.FromImage(bmp); using var brush = new SolidBrush(Application.Theme.PrimaryColor); gr.TextRenderingHint = TextRenderingHint.AntiAlias; gr.DrawString(date, font, brush, 0, 0); return bmp; } public override void OnThemeChanged() { themeChanged = true; } public override void OnSettingsChanged() { themeChanged = true; } private static string FormatDateTime(DateTime value, string format, string? timeZoneId = null) { try { return FormatGeneric(value, format, timeZoneId, CultureInfo.CurrentCulture); } catch (Exception ex) { return "ERR: " + ex.Message; } } private static string FormatGeneric( DateTime date, string formatStr, string? timeZoneId = null, CultureInfo? locale = null ) { var timeZone = timeZoneId != null ? TimeZoneInfo.FindSystemTimeZoneById(timeZoneId) : TimeZoneInfo.Local; locale ??= CultureInfo.CurrentCulture; var tzDate = TimeZoneInfo.ConvertTime(date, timeZone); var replacements = new Dictionary<string, string> { ["%dateFull"] = tzDate.ToString("D", locale), ["%dateLong"] = tzDate.ToString("D", locale), ["%dateMedium"] = tzDate.ToString("d", locale), ["%dateShort"] = tzDate.ToString("d", locale), ["%timeFull"] = tzDate.ToString("T", locale) + " " + (timeZone.IsDaylightSavingTime(tzDate) ? timeZone.DaylightName : timeZone.StandardName), ["%timeLong"] = tzDate.ToString("T", locale) + " " + (timeZone.IsDaylightSavingTime(tzDate) ? timeZone.DaylightName : timeZone.StandardName), ["%timeMedium"] = tzDate.ToString("T", locale), ["%timeShort"] = tzDate.ToString("t", locale), ["%dddd"] = tzDate.ToString("dddd", locale), ["%ddd"] = tzDate.ToString("ddd", locale), ["%yyyy"] = tzDate.ToString("yyyy", locale), ["%yy"] = tzDate.ToString("yy", locale), ["%y"] = tzDate.ToString("yyyy", locale), ["%Y"] = tzDate.ToString("yyyy", locale), ["%MMMM"] = tzDate.ToString("MMMM", locale), ["%MMM"] = tzDate.ToString("MMM", locale), ["%mm"] = tzDate.ToString("MM", locale), ["%m"] = tzDate.ToString("M", locale), ["%dd"] = tzDate.ToString("dd", locale), ["%d"] = tzDate.ToString("d", locale), ["%DDD"] = GetDayOfYearPadded(tzDate), ["%D"] = GetDayOfYear(tzDate), ["%hh"] = tzDate.ToString("hh", locale), ["%h"] = tzDate.ToString("%h", locale), ["%HH"] = tzDate.ToString("HH", locale), ["%H"] = tzDate.ToString("%H", locale), ["%ii"] = tzDate.ToString("mm", locale), ["%i"] = tzDate.ToString("%m", locale), ["%ss"] = tzDate.ToString("ss", locale), ["%s"] = tzDate.ToString("%s", locale), ["%SSS"] = tzDate.ToString("fff", locale), ["%S"] = tzDate.ToString("%f", locale), ["%a"] = GetAmPm(tzDate, locale), ["%A"] = GetAmPmUpper(tzDate, locale), ["%ww"] = GetIsoWeekPadded(tzDate), ["%w"] = GetIsoWeek(tzDate), ["%EE"] = tzDate.ToString("dddd", locale), ["%E"] = tzDate.ToString("ddd", locale), ["%e"] = ((int)tzDate.DayOfWeek).ToString(), ["%qq"] = GetQuarterPadded(tzDate), ["%q"] = GetQuarter(tzDate), ["%zz"] = timeZone.Id, ["%z"] = timeZone.IsDaylightSavingTime(tzDate) ? timeZone.DaylightName : timeZone.StandardName, }; var formatRegex = string.Join("|", replacements.Keys); return Regex.Replace( formatStr, formatRegex, match => replacements.TryGetValue(match.Value, out var replacement) ? replacement : match.Value ); string GetIsoWeek(DateTime d) { DayOfWeek day = locale.Calendar.GetDayOfWeek(d); if (day is >= DayOfWeek.Monday and <= DayOfWeek.Wednesday) { d = d.AddDays(3); } return locale.Calendar.GetWeekOfYear(d, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday).ToString(); } string GetAmPmUpper(DateTime d, CultureInfo l) => d.ToString("tt", l).ToUpper(); string GetAmPm(DateTime d, CultureInfo l) => d.ToString("tt", l).ToLower(); string GetQuarterPadded(DateTime d) => GetQuarter(d).PadLeft(2, '0'); string GetQuarter(DateTime d) => ((d.Month + 2) / 3).ToString(); string GetIsoWeekPadded(DateTime d) => GetIsoWeek(d).PadLeft(2, '0'); string GetDayOfYearPadded(DateTime d) => d.DayOfYear.ToString("D3"); string GetDayOfYear(DateTime d) => d.DayOfYear.ToString(); } } ```
Author
Owner

@jerry-monitor commented on GitHub (Jun 25, 2026):

The result is this without the time ever updating:

Image
<!-- gh-comment-id:4798545901 --> @jerry-monitor commented on GitHub (Jun 25, 2026): The result is this without the time ever updating: <img width="496" height="29" alt="Image" src="https://github.com/user-attachments/assets/5a421664-a06a-4ce3-b2aa-7ff14fe85bbc" />
Author
Owner

@Stone-Red-Code commented on GitHub (Jun 25, 2026):

Hi this seems to be caused by an issue with your code.

if (oldDateTime.Date == DateTime.Now.Date && !themeChanged)
{
    return null;
}

Specifically oldDateTime.Date == DateTime.Now.Date checks if the current date changed, which means it will only update once per day.

<!-- gh-comment-id:4798628152 --> @Stone-Red-Code commented on GitHub (Jun 25, 2026): Hi this seems to be caused by an issue with your code. ```cs if (oldDateTime.Date == DateTime.Now.Date && !themeChanged) { return null; } ``` Specifically `oldDateTime.Date == DateTime.Now.Date` checks if the current date changed, which means it will only update once per day.
Author
Owner

@jerry-monitor commented on GitHub (Jun 25, 2026):

Wow, that was silly of me, I could and should have caught that one... I thought I copied that from another plugin. Anyway, thanks, it works now. :)

<!-- gh-comment-id:4798679187 --> @jerry-monitor commented on GitHub (Jun 25, 2026): Wow, that was silly of me, I could and should have caught that one... I thought I copied that from another plugin. Anyway, thanks, it works now. :)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Stone_Red/DesktopMagic#4