private static void ThreadProc()
        {
#if NET20
            localOffset = (int)TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.UtcNow).TotalMinutes;
#else
            localOffset = (int)TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow).TotalMinutes;
#endif
            // Only check for offset changes every new minute (plus 1 second safety margin) to save
            // resources for clearing the TimeZoneInfo cache
            nextOffsetCheck = DateTime.UtcNow.Ticks / 600000000 * 600000000 + 610000000;

            do
            {
                try
                {
                    Thread.Sleep(CheckInterval);
                }
                catch (ThreadInterruptedException)
                {
                    // That's fine.
                }

                // Check for UTC time changes
                TimeSpan offset = DateTime.UtcNow - FL.UtcNow;
                if (Math.Abs(offset.TotalMilliseconds) >= FL.CheckTimeThreshold)
                {
                    FL.RebaseTime();

                    string msg  = "System time changed by " + offset.TotalMilliseconds.ToString("0.0", CultureInfo.InvariantCulture) + " ms";
                    var    item = new FieldLogTextItem(FieldLogPriority.Notice, msg, "Changes less than " + FL.CheckTimeThreshold + " ms are not reported.");
                    // Discard this log item if there was no other item logged within the last
                    // 10 seconds because it wouldn't be interesting anyway. If no other log items
                    // may have discontinuous timestamps, the time recalibration can occur silently.
                    FL.LogInternal(item, TimeSpan.FromSeconds(10));
                    Debug.WriteLine(msg);
                    prevLoggedOffset = 0;
                }
                else if (FL.LogTimeThreshold >= 0 &&
                         Math.Abs(offset.TotalMilliseconds - prevLoggedOffset) > FL.LogTimeThreshold)
                {
                    FL.TraceData("System time offset", offset.TotalMilliseconds);
                    prevLoggedOffset = offset.TotalMilliseconds;
                }

                // Check for local time zone changes
                if (DateTime.UtcNow.Ticks >= nextOffsetCheck)
                {
                    // Clear the cache to get the real current setting
#if NET20
                    int newLocalOffset = (int)TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.UtcNow).TotalMinutes;
#else
                    TimeZoneInfo.ClearCachedData();
                    int newLocalOffset = (int)TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow).TotalMinutes;
#endif
                    if (newLocalOffset != localOffset)
                    {
                        int hours = localOffset / 60;
                        int mins  = Math.Abs(localOffset) % 60;

                        int newHours = newLocalOffset / 60;
                        int newMins  = Math.Abs(newLocalOffset) % 60;

                        localOffset = newLocalOffset;

                        string msg = "Local time UTC offset changed from " +
                                     hours.ToString("+00;-00;+00") + ":" + mins.ToString("00") + " to " +
                                     newHours.ToString("+00;-00;+00") + ":" + newMins.ToString("00");
                        string details = "\u0001UtcOffset=" + newLocalOffset;
                        FL.Notice(msg, details);
                        Debug.WriteLine(msg);
                    }
                    nextOffsetCheck = DateTime.UtcNow.Ticks / 600000000 * 600000000 + 610000000;
                }
            }while (!cancelPending);
        }