Skip to content

Instantly share code, notes, and snippets.

@vicly
Last active February 19, 2020 04:38
Show Gist options
  • Save vicly/8c9ad2b1a069ce9f5b49504625bb17f6 to your computer and use it in GitHub Desktop.
Save vicly/8c9ad2b1a069ce9f5b49504625bb17f6 to your computer and use it in GitHub Desktop.
[Time] #Note #Fundamental #Time

TAI - International Atomic Time (Temps Atomique International = TAI)

部署在50多个国家的200多个原子时钟的平均值 TAI-UT1大约是1958年1月1日

UT - Universal Time 世界时

Defined by the Earth's rotation (GPS satellites used) UT0完全按照天体运行计算出来的时间 UT1在UT0上做了调整 UT2在UT0和UT1上做了调整

UTC & GMT

UTC - Universal Time Coordinated 协调世界时 在0经度(本初子午线)的时间 精度为“秒“ 基于原子时钟 时间是均匀的 UTC源自1972年 “闰秒”保证与UT1误差不超过0.9秒 (UT1 - UTC = DUT1,DUT1 is maintained via leap seconds)

GMT - Greenwich Mean Time 格林威治时间 What UTC used to be called(UTC定义了世界标准时间,1972年以前,GMT就是世界标准时间)

UTC + 时区差 = 本地时间

时区差 东为正,西为负

08 Nov 2010 10:42:22 +800 本地时间为2010年11月08日10点42分22秒,本地时间领先UTC八个小时

Unix time

Measured as the number of seconds since 1970.1.1 UTC

When programming

Timezone is a presentation-layer problem! Most of your code should not deal with timezone or local time, it should use unix time.

Avoid re-implement stuff about timezone convension or formatting, use your language built-in function.

When recording a point in time, use Unix time, it's UTC.

When storing a timestamp, store unix time, it's a single number.

If trying to store human-readable time, consider store it along with unix time, not instead of unix time

When display time, always include the timezone offset. A time format without offset is useless.

The system clock is inaccurate. On a nework? Every other system's clock is differently inaccurate.

The system clock can/will jump backwards and forward. Your program should survive this.

ntpd can change the system time in two ways: ..* Step: correct time directly ..* Slew: changing the frequency of the clock so that it slowly drifts toward the correct time (GOOD!)

MYSQL (4.x/5.x at least) stores DATETIME type as YYYY-MM-DD HH:MM:SS string, no offset. Use UNIX_TIMESTAMP() and FROM_UNIXTIME() to store as integer

Notes

How to present an exactly accurate a time

  1. Unix time: long, all OS/lib supports it
  2. +: e.g. 2014-10-20T11:39:33.556+800

Gregorian calendar system

http://www.joda.org/joda-time/cal_gregorian.html

Used by the modern business world.

Introduced on 1582-10-15, to replace Julian calendar.

Can NOT be used to describe date time before 1583.

The Gregorian chronology in Joda-Time is equivalent* to the ISO chronology, and uses Gregorian rules for all time. The difference is "century", e.g. 2005 in Gregorian is 21st century, but in ISO is 20, since ISO defines a century as the first two digits of the year.

Basic

Universal Time

  • single global point of reference. No time zones.
  • Sync via Network Time Protocol (NTP)
  • GMT = Greenwich Mean Time
  • UTC = Coordinated Universal Time
    • Sientifically accurate
    • Leap seconds
  • In morden time, GMT and UTC means the same thing.
  • use UTC
    • as a timekeeping system
    • as the reference point from an offset (UTC-07:00)

Daylight Saving Time

  • Government mandated clock adjustments
  • Not applicable to every timezone
  • Not applied the same in every year
  • Same UTC offset, the daylight saving time rules might not be different

ISO8601

  • use accurate universal format to store DATA of time
  • DO NOT invent your own date data format

Scope

  • Date and time:
    • 2013-12-20 11:55:30
    • usecase: an event time
  • Date:
    • 2013-12-20
    • usecase: birthday
  • Time of Day:
    • 10:00:00 PM 22:00:00
    • usecase: business hours
  • Elapsed Time
    • 33 hours 15 mins
    • usecase: duration
  • Imperfect time perios
    • 1 year: 365 days / 366 days?
    • 3 months: feb 28 / 29 days?
    • 10 days: if daylight saving, add/minus X hours?
    • usecase: Scheduling, Estimating

TimeZone

Time zone is NOT an offset.

What is a Time Zone?

  • defines the configuration of local clocks (covers all time within the region)
  • has a common or legal name
  • has a standard offset from UTC
  • includes daylight saving time rules
  • includes history of changes, so current rule is not always true
    • 1987 - 2006
      • start: 1st sunday in April
      • ends: last sunday in Oct
    • 2007 - Present
      • start: 2nd sunday in March
      • ends: 1st sunday in Nov

Many time zones share offsets, example: UTC+02:00

  • Estern European Time: has daylight saving
  • Israel Standad Time: has daylight saving, but start/end is different
  • Central Africa Time: no daylight saving

FALSE: "time zone names and abbreviation are unique" "CST" could be

  • Central standard time (North America) - UTC-06:00
  • Central Standard time (Australia)) - UTC-09:30
  • China standard time
  • Cuba standard time

FALSE: "there are only 24 possible offsets, since they are in one hour increments". Example: To Australia

  • WST: UTC+8:00
  • CWST: UTC+8:45
  • CST: UTC+9:30
  • CDT: UTC+10:30
  • EST: UTC+10:00

FALSE: "daylight saving time == 1 hour advance"

  • LHST: UTC+10:30
  • LHDT: UTC+11:00

FALSE: "time zone will never chage"

  • rules controlled by govement

FALSE: "only two daylight saving time transisation in any given year"

  • Egypt in 2010
    • First DST: April 30 to Aug 10
    • Second DST: Sep 10 to Sep 30

IANA Time Zone Database: iana.org/time-zones

MetaZones

  • groups of timezones that can span countries
  • cldr.unicode.org

POSIX Time Zone

  • Portable Operation System Interface
  • Old standard
  • DO NOT use it, treat as deprecated

Date and Time Formats

ISO8601 Extended Format

Format Exmaple
YYYY-MM-DD 2012-09-01
HH:MM:SS 01:23:45
HH:MM:SS.fffffff 01:23:33.1234567
HH:MM:SS.fffffffZ 01:23:33.1234567Z
HH:MM:SS.fffffff[+/-]HH 01:23:33.1234567+02
HH:MM:SS.fffffff[+/-]HH:MM 01:23:33.1234567+05:30
YYYY-MM-DDTHH:MM:SS.fffffff 2012-09-22T01:23:33.1234567
YYYY-MM-DDTHH:MM:SS.fffffffZ 2012-09-22T01:23:33.1234567Z
YYYY-MM-DDTHH:MM:SS.fffffff[+/-]HH 2012-09-22T01:23:33.1234567+05
YYYY-MM-DDTHH:MM:SS.fffffff[+/-]HH:MM 2012-09-22T01:23:33.1234567+05:30

ISO8601 Basic Format

Format Exmaple
YYYYMMDD 20120901
HHMMSS 012345
HHMMSS.fffffff 012333.1234567
HHMMSS.fffffffZ 012333.1234567Z
HHMMSS.fffffff[+/-]HH 012333.1234567+02
HHMMSS.fffffff[+/-]HHMM 012333.1234567+0530
YYYYMMDDZHHMMSS.fffffff 20120922T012333.1234567
YYYYMMDDZHHMMSS.fffffffZ 20120922T012333.1234567Z
YYYYMMDDZHHMMSS.fffffff[+/-]HH 20120922T012333.1234567+04
YYYYMMDDZHHMMSS.fffffff[+/-]HHMM 20120922T012333.1234567+0430

RFC3339

  • a subset of ISO8601 extended format
  • specifically for timestamps
    • date and time are both required
    • seconds are required; decimals are optional
    • UTC "Z" or Offset is required
  • Midnight is always 00:00:00
  • Allow negative offset -00:00: UTC is known, but an "unknown local offset"

RFC822/1123

  • Old format
    • no fractional seconds
    • english only
    • poor use of timezone abbreviations
  • Used in HTTP headers
  • Used by JavaScript
  • Example:
    • Tue, 31 Dec 2013 01:23:45 GMT
    • Tue 31 Dec 2013 01:23:45 GMT+0530
  • Variations
    • Twitter API: Tue 31 Dec 01:23:45 0530 2013

Do not care this old format too much

UNIX Time

  • Interger Timestamp
  • Seconds since Jan 1st 1970 UTC or in milliseconds
  • Aka. "epoch time"
  • time before 1970 will be negative number

Time Span and Duration Formats

HH:MM:SS.fffffff

  • 23:59:59.9999999
  • 2.23:59:59.9999999: 2 days 23 hours 59min 59sec 9999999

ISO8601 Duration Format

  • P3Y: 3 years
  • P5M: 5 months
  • P5W: 5 weeks
  • PT15H: 15 hours
  • PT90M: 90 mins
  • PT20S: 20 sec
  • P3Y5M8W15DT36H90M2.576S
  • Be careful with "Calendar Math", "+ - => different result":
    • 2013-7-31 + P2M = 2013-9-30 - P2M = 2013-7-30
    • 2012-2-29 + P1Y = 2013-2-28 - P1Y = 2012-2-28

JSON and XML

  • JSON
    • do not define a date format
    • options
      • ISO8601 extended format (recommended)
      • UNIX time
      • DO NOT USE ASP.NET format: /Date(1388353626123-0700)/
  • XML
    • do not define a date format
    • XSD uses ISO8601 extended format
    • xsd:date: 2013-09-23
    • xsd:time: 01:23:45.123
    • xsd:dateTime: 2013-09-23T01:23:45.123Z 2013-09-23T01:23:45.123+07:00 2013-09-23T01:23:45.123
    • xsd:duration: P3Y5M2DT5H

Date and Time in JavaScript

  • do not use built-in date
  • dt.toISOString() => 2013-12-31T09:33:23.000Z
  • Recommendations:
    • opt1: build the string yourself
    • opt2: use a library Moment.js

Time Zone Selection

Best Practice

  • Understand context Are you using correct scope?

    1. date + time VS. date only
    2. time of day VS. elapsed time
    3. elapsed duration VS. calendric period
  • Could the scope/perspective be lost when round-tripped?

    • app <-> db
    • apiclient <-> apiserver
    • datetime to date at midnight
    • UTC to local or unspecified
  • Whose day is it? "today", "last week", "by Friday", "this month"

    • customer day or business day
    • date or date range based query?
    • summary report (daily, weekly, monthly, etc.)
    • time-based business log
  • Understand timezone: TimeZone !> Offset

    • offset only applies to single point of time
    • timezone have multiple offsets
    • daylight saving time
      • is not used everywhere
      • is not uniform where it's used
    • timezone abbreviations are often ambiguous
    • time zone rules are changing
  • Calculating duration

    • Avoid calculating in local time, use UTC for calculation
  • Local time

    • Log timestamp in UTC or in local time with offset
  • Server time: avoid using server's timezone

  • Calculating age

    • Leap day birthday
      • leap year: Feb 29
      • non-leap year: Feb 28? or Mar 1? It's business question
// Mar 1
DateTime today = TimeZoneInfo.ConvertTimeFromUtc(
    DateTime.UtcNow, targetTimeZone
).Date;

int age = today.Year - birthday.Year;
if (birthday.Month > today.Month ||
   (birtthday.Month == today.Month && birthday.Day > today.Day)) {
       age --;
}
  • Working with Range

    • [start, end): good to do duration calculation
    • clock duration: hours = start <= end ? end - start : end - start + 24hours
  • Scheduling Futrue Event

    • use Quartz
    • daily != 24 hours
    • event should be recored in local time, not UTC: Daily 08:00 Americ/Los_Angeles

Good online resources

https://stackoverflow.com/questions/2532729/daylight-saving-time-and-time-zone-best-practices/2532962#2532962

https://stackoverflow.com/questions/19626177/how-to-store-repeating-dates-keeping-in-mind-daylight-savings-time/19627330#19627330

http://www.creativedeletion.com/2015/03/19/persisting_future_datetimes.html

https://stackoverflow.com/tags/timezone/info

An offset is just a number that represents how far a particular date/time value is ahead or behind UTC.

  • Most offsets are expressed in whole hours.
  • But there are many that are 30-minute offset.
  • And there are a few that are 45-minute offset.

A time zone contains much more:

  • A name or ID that can be used to identify the zone.
  • One or more offsets from UTC
  • The specific dates and times that the zone transitions between offsets.
  • Sometimes, a separate language-specific display name that can be presented to a user.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment