15 FUNCTION_TAKES_EXACTLY(1);
17 if (!IS_INTEGER(argv[0]) && !IS_FLOATING(argv[0])) {
18 return TYPE_ERROR(
int or
float,argv[0]);
21 unsigned int usecs = (IS_INTEGER(argv[0]) ? AS_INTEGER(argv[0]) :
22 (IS_FLOATING(argv[0]) ? AS_FLOATING(argv[0]) : 0)) *
27 return BOOLEAN_VAL(1);
31 FUNCTION_TAKES_NONE();
34 gettimeofday(&tv,NULL);
36 double out = (double)tv.tv_sec + (
double)tv.tv_usec / 1000000.0;
38 return FLOATING_VAL(out);
48 #define IS_struct_time(o) (krk_isInstanceOf(o,struct_time))
49 #define AS_struct_time(o) ((struct struct_time_obj*)AS_OBJECT(o))
50 #define CURRENT_CTYPE struct struct_time_obj *
51 #define CURRENT_NAME self
53 KRK_Method(struct_time,__init__) {
55 if (!
krk_parseArgs(
".V:struct_time", (
const char *[]){
"iterable"}, &seq))
return NONE_VAL();
56 if (!IS_TUPLE(seq) || AS_TUPLE(seq)->values.count != 9)
return krk_runtimeError(
vm.exceptions->notImplementedError,
"sequence other than 9-tuple unsupported");
57 for (
int i = 0; i < 9; ++i) {
58 if (!IS_INTEGER(AS_TUPLE(seq)->values.values[i]))
return krk_runtimeError(
vm.exceptions->valueError,
"expected int, not %T", AS_TUPLE(seq)->values.values[i]);
61 self->_value.tm_year = AS_INTEGER(AS_TUPLE(seq)->values.values[0]) - 1900;
62 self->_value.tm_mon = AS_INTEGER(AS_TUPLE(seq)->values.values[1]) - 1;
63 self->_value.tm_mday = AS_INTEGER(AS_TUPLE(seq)->values.values[2]);
64 self->_value.tm_hour = AS_INTEGER(AS_TUPLE(seq)->values.values[3]);
65 self->_value.tm_min = AS_INTEGER(AS_TUPLE(seq)->values.values[4]);
66 self->_value.tm_sec = AS_INTEGER(AS_TUPLE(seq)->values.values[5]);
67 self->_value.tm_wday = (AS_INTEGER(AS_TUPLE(seq)->values.values[6])+6)%7;
68 self->_value.tm_yday = AS_INTEGER(AS_TUPLE(seq)->values.values[7]) - 1;
69 self->_value.tm_isdst = AS_INTEGER(AS_TUPLE(seq)->values.values[8]);
74 KRK_Method(struct_time,tm_year) {
return INTEGER_VAL(self->_value.tm_year + 1900); }
75 KRK_Method(struct_time,tm_mon) {
return INTEGER_VAL(self->_value.tm_mon + 1); }
76 KRK_Method(struct_time,tm_mday) {
return INTEGER_VAL(self->_value.tm_mday); }
77 KRK_Method(struct_time,tm_hour) {
return INTEGER_VAL(self->_value.tm_hour); }
78 KRK_Method(struct_time,tm_min) {
return INTEGER_VAL(self->_value.tm_min); }
79 KRK_Method(struct_time,tm_sec) {
return INTEGER_VAL(self->_value.tm_sec); }
80 KRK_Method(struct_time,tm_wday) {
return INTEGER_VAL((self->_value.tm_wday+1)%7); }
81 KRK_Method(struct_time,tm_yday) {
return INTEGER_VAL(self->_value.tm_yday+1); }
82 KRK_Method(struct_time,tm_isdst) {
return INTEGER_VAL(self->_value.tm_isdst); }
84 KRK_Method(struct_time,__repr__) {
85 return krk_stringFromFormat(
86 "time.struct_time(tm_year=%d, tm_mon=%d, tm_mday=%d, tm_hour=%d, tm_min=%d, "
87 "tm_sec=%d, tm_wday=%d, tm_yday=%d, tm_isdst=%d)",
88 self->_value.tm_year + 1900,
89 self->_value.tm_mon + 1,
94 (self->_value.tm_wday + 1) % 7,
95 self->_value.tm_yday + 1,
96 self->_value.tm_isdst);
99 static time_t time_or_now(
int has_arg,
long long secs) {
102 gettimeofday(&tv,NULL);
103 return (time_t)tv.tv_sec;
109 static void tm_or_now(
const struct struct_time_obj * t,
struct tm * _time) {
111 memcpy(_time,&t->_value,
sizeof(
struct tm));
114 gettimeofday(&tv,NULL);
115 time_t time = tv.tv_sec;
116 localtime_r(&time,_time);
120 KRK_Function(localtime) {
123 if (!
krk_parseArgs(
"|L?",(
const char*[]){
"seconds"},&gave_seconds, &seconds))
return NONE_VAL();
124 time_t time = time_or_now(gave_seconds, seconds);
130 if (!localtime_r(&time, &out->_value))
return krk_runtimeError(
vm.exceptions->valueError,
"?");
135 static KrkValue krk_asctime(
const struct tm *_time) {
137 static const char * monNames[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"};
138 static const char * dayNames[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"};
144 snprintf(buf,39,
"%s %s%3d %.2d:%.2d:%.2d %d",
145 dayNames[_time->tm_wday % 7],
146 monNames[_time->tm_mon % 12],
151 _time->tm_year + 1900);
156 KRK_Function(asctime) {
158 if (!
krk_parseArgs(
"|O!",(
const char*[]){
"t"},struct_time,&t))
return NONE_VAL();
161 return krk_asctime(&_time);
164 KRK_Function(ctime) {
167 if (!
krk_parseArgs(
"|L?",(
const char*[]){
"secs"},&has_arg,&secs))
return NONE_VAL();
168 time_t time = time_or_now(has_arg, secs);
170 if (!localtime_r(&time, &_time))
return krk_runtimeError(
vm.exceptions->valueError,
"?");
172 return krk_asctime(&_time);
175 KRK_Function(gmtime) {
178 if (!
krk_parseArgs(
"|L?",(
const char*[]){
"secs"},&gave_seconds, &seconds))
return NONE_VAL();
179 time_t time = time_or_now(gave_seconds, seconds);
185 if (!gmtime_r(&time, &out->_value))
return krk_runtimeError(
vm.exceptions->valueError,
"?");
190 KRK_Function(mktime) {
192 if (!
krk_parseArgs(
"O!",(
const char*[]){
"t"},struct_time,&t))
return NONE_VAL();
195 memcpy(&_time,&t->_value,
sizeof(
struct tm));
197 time_t out = mktime(&_time);
198 if (out == -1 && _time.tm_wday == -1)
return krk_runtimeError(
vm.exceptions->valueError,
"invalid argument to mktime");
199 return FLOATING_VAL(out);
202 KRK_Function(strftime) {
205 if (!
krk_parseArgs(
"s|O!",(
const char*[]){
"format",
"t"},&format,struct_time,&t))
return NONE_VAL();
212 size_t fmt_len = strlen(format);
215 char * buf = malloc(size);
216 size_t ret = strftime(buf,size,format,&_time);
217 if (ret || size > fmt_len * 256) {
228 KRK_DOC(module,
"@brief Provides timekeeping functions.");
229 KRK_DOC(BIND_FUNC(module,sleep),
"@brief Pause execution of the current thread.\n"
230 "@arguments secs\n\n"
231 "Uses the system @c usleep() function to sleep for @p secs seconds, which may be a @ref float or @ref int. "
232 "The available precision is platform-dependent.");
233 KRK_DOC(BIND_FUNC(module,time),
"@brief Return the elapsed seconds since the system epoch.\n\n"
234 "Returns a @ref float representation of the number of seconds since the platform's epoch date. "
235 "On POSIX platforms, this is the number of seconds since 1 January 1970. "
236 "The precision of the return value is platform-dependent.");
238 krk_makeClass(module, &struct_time,
"struct_time", KRK_BASE_CLASS(
object));
240 KRK_DOC(struct_time,
"Time value returned by various functions.");
241 KRK_DOC(BIND_METHOD(struct_time,__init__),
"@arguments iterable: tuple\n\n"
242 "Create a @ref struct_time from a 9-tuple of @ref int values.\n"
243 "The format of @p iterable is `(tm_year,tm_mon,tm_mday,tm_hour,tm_min,tm_sec,tm_wday,tm_yday,tm_isdst)`.");
244 KRK_DOC(BIND_PROP(struct_time,tm_year),
"Calendar year");
245 KRK_DOC(BIND_PROP(struct_time,tm_mon),
"Month, [1, 12]");
246 KRK_DOC(BIND_PROP(struct_time,tm_mday),
"Day of the month, [1, 31]");
247 KRK_DOC(BIND_PROP(struct_time,tm_hour),
"Clock hour, [0, 23]");
248 KRK_DOC(BIND_PROP(struct_time,tm_min),
"Clock minute, [0, 59]");
249 KRK_DOC(BIND_PROP(struct_time,tm_sec),
"Clock seconds, [0, 61] (maybe, due to leap seconds, depends on platform)");
250 KRK_DOC(BIND_PROP(struct_time,tm_wday),
"Day of week, [0, 6], 0 is Monday.");
251 KRK_DOC(BIND_PROP(struct_time,tm_yday),
"Day of year [1, 366]");
252 KRK_DOC(BIND_PROP(struct_time,tm_isdst),
"0, 1, -1 for unknown");
253 BIND_METHOD(struct_time,__repr__);
256 KRK_DOC(BIND_FUNC(module,localtime),
"@brief Convert seconds since epoch to local time.\n"
257 "@arguments seconds=time.time()\n\n"
258 "If @p seconds is not provided, the current @ref time is used.");
259 KRK_DOC(BIND_FUNC(module,asctime),
"@brief Convert time to string.\n"
260 "@arguments t=time.localtime()\n\n"
261 "If @p t is not provided, the current @ref localtime is used.");
262 KRK_DOC(BIND_FUNC(module,ctime),
"@brief Convert seconds since epoch to string.\n"
263 "@arguments secs=time.time()\n\n"
264 "If @p secs is not provided, the current @ref time is used.");
265 KRK_DOC(BIND_FUNC(module,gmtime),
"@brief Convert seconds since epoch to UTC time.\n"
266 "@arguments secs=time.time()\n\n"
267 "If @p secs is not provided, the current @ref time is used.");
268 KRK_DOC(BIND_FUNC(module,mktime),
"@brief Convert from local time to seconds since epoch.\n"
270 "For compatibility with @ref time a @ref float is returned.");
271 KRK_DOC(BIND_FUNC(module,strftime),
"@brief Format time string with system function.\n"
272 "@arguments format,t=time.localtime()\n\n"
273 "Uses the system `strftime` C function to convert a @ref struct_time to a string.\n"
274 "If @p t is not provided, the current @ref localtime is used.");
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Struct definitions for core object types.
size_t allocSize
Size to allocate when creating instances of this class.
KrkClass * krk_makeClass(KrkInstance *module, KrkClass **_class, const char *name, KrkClass *base)
Convenience function for creating new types.
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
KrkString * krk_copyString(const char *chars, size_t length)
Obtain a string object representation of the given C string.
Stack reference or primative value.
Utilities for creating native bindings.
#define krk_parseArgs(f, n,...)
Parse arguments to a function while accepting keyword arguments.
#define KRK_DOC(thing, text)
Attach documentation to a thing of various types.
Definitions for primitive stack references.
Core API for the bytecode virtual machine.
#define vm
Convenience macro for namespacing.
KrkValue krk_pop(void)
Pop the top of the stack.
void krk_push(KrkValue value)
Push a stack value.