1 /** 2 * Proleptic Gregorian calendar: time 3 * 4 * Copyright: Maxim Freck, 2016–2017. 5 * Authors: Maxim Freck <maxim@freck.pp.ru> 6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 */ 8 module pgc.time; 9 10 public import pgc.exception; 11 12 alias Time = uint; 13 14 /*********************************** 15 * Returns: Time uint for a given time value (hour, minute, second and split) 16 * 17 * Params: 18 * hour = the number of the hour 19 * minute = the number of the minute 20 * second = the number of the second 21 * split = the number of the split (1/32767 of a second) 22 */ 23 pure Time mkTime(int hour, int minute, int second, int split = 0) @safe 24 { 25 assertTime(hour, minute, second, split); 26 return (((hour & 0x1F) << 27) | ((minute & 0x3F) << 21) | ((second & 0x3F) << 15) | (split & 0x3FFF)); 27 } 28 29 /*********************************** 30 * Checks the validity of a time 31 * 32 * Params: 33 * hour = the number of the hour 34 * month = the number of the month 35 * year = the number of the year 36 */ 37 pure private void assertTime(int hour, int minute, int second, int split = 0) @safe 38 { 39 import std.conv: to; 40 if (hour < 0 || hour > 23) throw new PgcException("Invalid hour value: "~to!string(hour)); 41 if (minute < 0 || minute > 59) throw new PgcException("Invalid minute value: "~to!string(minute)); 42 if (second < 0 || second > 59) throw new PgcException("Invalid second value: "~to!string(second)); 43 if (split < 0 || split > 32_768) throw new PgcException("Split "~to!string(split)~" is out of bound [0..32768]"); 44 } 45 46 /*********************************** 47 * Returns: the hour of a given time 48 * 49 * Params: 50 * t = time 51 */ 52 pure nothrow ubyte hour(Time t) @safe @nogc 53 { 54 return cast(ubyte)((t >> 27) & 0x1F); 55 } 56 57 /*********************************** 58 * Returns: the minute of a given time 59 * 60 * Params: 61 * t = time 62 */ 63 pure nothrow ubyte minute(Time t) @safe @nogc 64 { 65 return cast(ubyte)((t >> 21) & 0x3F); 66 } 67 68 /*********************************** 69 * Returns: the second of a given time 70 * 71 * Params: 72 * t = time 73 */ 74 pure nothrow ubyte second(Time t) @safe @nogc 75 { 76 return cast(ubyte)((t >> 15) & 0x3F); 77 } 78 79 /*********************************** 80 * Returns: the split (1/32767) of a given time 81 * 82 * Params: 83 * t = time 84 */ 85 pure nothrow ushort split(Time t) @safe @nogc 86 { 87 return cast(ushort)(t & 0x7FFF); 88 } 89 90 version(Posix) { 91 import core.sys.posix.sys.time: gettimeofday, gmtime, localtime, timeval; 92 93 /*********************************** 94 * Returns: the current time in UTC 95 */ 96 Time nowUTC() 97 { 98 timeval time; 99 gettimeofday(&time, null); 100 auto tm = gmtime(&time.tv_sec); 101 102 return mkTime(tm.tm_hour, tm.tm_min, tm.tm_sec, cast(int)(time.tv_usec/31)); 103 } 104 105 /*********************************** 106 * Returns: the current local time 107 */ 108 Time nowLocal() 109 { 110 timeval time; 111 gettimeofday(&time, null); 112 auto tm = localtime(&time.tv_sec); 113 114 return mkTime(tm.tm_hour, tm.tm_min, tm.tm_sec, cast(int)(time.tv_usec/31)); 115 } 116 } 117 118 version(Windows) { 119 import core.sys.windows.windows: GetLocalTime, GetSystemTime, SYSTEMTIME; 120 121 /*********************************** 122 * Returns: the current time in UTC 123 */ 124 Time nowUTC() 125 { 126 SYSTEMTIME time; 127 GetSystemTime(&time); 128 return mkTime(time.wHour, time.wMinute, time.wSecond, time.wMilliseconds*16); 129 } 130 131 /*********************************** 132 * Returns: the current local time 133 */ 134 Time nowLocal() 135 { 136 SYSTEMTIME time; 137 GetLocalTime(&time); 138 return mkTime(time.wHour, time.wMinute, time.wSecond, time.wMilliseconds*16); 139 } 140 }