strptime 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8b40c7a57148fcfb7d779334d8aa5d69b20cceb4
4
+ data.tar.gz: 6ef5e81c537b35fb66cc9dc296175fead462b1e5
5
+ SHA512:
6
+ metadata.gz: 40572649080b934c44e382b67fd8fecc61e45adf3055349980ad1632c1e47beb4fc1fce9d4727cb3384f587753f4d217ec7b9726d0bfdebaeccc7d0177b582db
7
+ data.tar.gz: 87977f0298c47ed9a4882d37fee7ce71047255b5d82b4f2072a8e2edaf08cbdb9cab19e2641ef0488bdee0a5c2cfd7a09fc5a5510be45ac5ccd0e3fa5f0a3935
@@ -0,0 +1,67 @@
1
+ ---
2
+ Language: Cpp
3
+ # BasedOnStyle: LLVM
4
+ AccessModifierOffset: -2
5
+ AlignAfterOpenBracket: true
6
+ AlignConsecutiveAssignments: false
7
+ AlignEscapedNewlinesLeft: false
8
+ AlignOperands: true
9
+ AlignTrailingComments: true
10
+ AllowAllParametersOfDeclarationOnNextLine: true
11
+ AllowShortBlocksOnASingleLine: false
12
+ AllowShortCaseLabelsOnASingleLine: true
13
+ AllowShortFunctionsOnASingleLine: All
14
+ AllowShortIfStatementsOnASingleLine: true
15
+ AllowShortLoopsOnASingleLine: false
16
+ AlwaysBreakAfterDefinitionReturnType: All
17
+ AlwaysBreakBeforeMultilineStrings: false
18
+ AlwaysBreakTemplateDeclarations: false
19
+ BinPackArguments: true
20
+ BinPackParameters: true
21
+ BreakBeforeBinaryOperators: None
22
+ BreakBeforeBraces: Stroustrup
23
+ BreakBeforeTernaryOperators: true
24
+ BreakConstructorInitializersBeforeComma: false
25
+ ColumnLimit: 80
26
+ CommentPragmas: '^ IWYU pragma:'
27
+ ConstructorInitializerAllOnOneLineOrOnePerLine: false
28
+ ConstructorInitializerIndentWidth: 4
29
+ ContinuationIndentWidth: 4
30
+ Cpp11BracedListStyle: true
31
+ DerivePointerAlignment: false
32
+ DisableFormat: false
33
+ ExperimentalAutoDetectBinPacking: false
34
+ ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
35
+ IndentCaseLabels: false
36
+ IndentWidth: 4
37
+ IndentWrappedFunctionNames: false
38
+ KeepEmptyLinesAtTheStartOfBlocks: true
39
+ MacroBlockBegin: ''
40
+ MacroBlockEnd: ''
41
+ MaxEmptyLinesToKeep: 1
42
+ NamespaceIndentation: None
43
+ ObjCBlockIndentWidth: 2
44
+ ObjCSpaceAfterProperty: false
45
+ ObjCSpaceBeforeProtocolList: true
46
+ PenaltyBreakBeforeFirstCallParameter: 19
47
+ PenaltyBreakComment: 300
48
+ PenaltyBreakFirstLessLess: 120
49
+ PenaltyBreakString: 1000
50
+ PenaltyExcessCharacter: 1000000
51
+ PenaltyReturnTypeOnItsOwnLine: 60
52
+ PointerAlignment: Right
53
+ SpaceAfterCStyleCast: false
54
+ SpaceBeforeAssignmentOperators: true
55
+ SpaceBeforeParens: ControlStatements
56
+ SpaceInEmptyParentheses: false
57
+ SpacesBeforeTrailingComments: 1
58
+ SpacesInAngles: false
59
+ SpacesInContainerLiterals: true
60
+ SpacesInCStyleCastParentheses: false
61
+ SpacesInParentheses: false
62
+ SpacesInSquareBrackets: false
63
+ Standard: Cpp11
64
+ TabWidth: 8
65
+ UseTab: Always
66
+ ...
67
+
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.swp
13
+ *.o
14
+ *.a
15
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ os:
3
+ - linux
4
+ - osx
5
+ rvm:
6
+ - 2.0.0-p647
7
+ - 2.1.7
8
+ - 2.2.3
9
+ - 2.2.3-clang
10
+ before_install:
11
+ - gem install bundler
12
+ cache: bundler
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in strptime.gemspec
4
+ gemspec
@@ -0,0 +1,26 @@
1
+ Copyright (C) 2015 NARUSE, Yui. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
23
+
24
+ ext/strptime/strptime.c:
25
+ date_strptime.c: Coded by Tadayoshi Funaba 2011,2012
26
+ Copyright (C) 2004-2007 Koichi Sasada
@@ -0,0 +1,41 @@
1
+ # Strptime
2
+
3
+ [![Build Status](https://travis-ci.org/nurse/strptime.png)](https://travis-ci.org/nurse/strptime)
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/strptime`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ TODO: Delete this and the text above, and describe your gem
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'strptime'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install strptime
24
+
25
+ ## Usage
26
+
27
+ TODO: Write usage instructions here
28
+
29
+ ## Development
30
+
31
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
32
+
33
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
34
+
35
+ ## Contributing
36
+
37
+ 1. Fork it ( https://github.com/[my-github-username]/strptime/fork )
38
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
39
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
40
+ 4. Push to the branch (`git push origin my-new-feature`)
41
+ 5. Create a new Pull Request
@@ -0,0 +1,28 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => [:compile, :spec]
8
+ require "rake/extensiontask"
9
+
10
+ task :build => :compile
11
+ task :spec => :compile
12
+
13
+ spec = eval File.read("strptime.gemspec")
14
+ Rake::ExtensionTask.new("strptime", spec) do |ext|
15
+ ext.ext_dir = 'ext/strptime'
16
+ ext.cross_compile = true
17
+ ext.lib_dir = File.join(*['lib', 'strptime', ENV['FAT_DIR']].compact)
18
+ # cross_platform names are of MRI's platform name
19
+ ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
20
+ end
21
+
22
+ namespace :build do
23
+ desc 'Build gems for Windows per rake-compiler-dock'
24
+ task :windows do
25
+ require 'rake_compiler_dock'
26
+ RakeCompilerDock.sh 'bundle && rake cross native gem RUBY_CC_VERSION=2.0.0:2.1.7:2.2.3'
27
+ end
28
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "strptime"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ require "mkmf"
2
+
3
+ have_func 'timegm', 'time.h' or 'timegm(3) is required'
4
+
5
+ create_makefile("strptime/strptime")
@@ -0,0 +1,380 @@
1
+ /**********************************************************************
2
+
3
+ time.c -
4
+
5
+ $Author$
6
+ created at: Tue Dec 28 14:31:59 JST 1993
7
+
8
+ Copyright (C) 1993-2007 Yukihiro Matsumoto
9
+
10
+ **********************************************************************/
11
+
12
+ #include "ruby.h"
13
+
14
+ #include <time.h>
15
+ #if defined(HAVE_SYS_TIME_H)
16
+ #include <sys/time.h>
17
+ #endif
18
+
19
+ /* rbtime_timespec_new */
20
+ typedef uint64_t WIDEVALUE;
21
+ typedef WIDEVALUE wideval_t;
22
+
23
+ #ifdef PACKED_STRUCT_UNALIGNED
24
+ PACKED_STRUCT_UNALIGNED(struct vtm {
25
+ VALUE year; /* 2000 for example. Integer. */
26
+ VALUE subsecx; /* 0 <= subsecx < TIME_SCALE. possibly Rational. */
27
+ VALUE utc_offset; /* -3600 as -01:00 for example. possibly Rational. */
28
+ const char *zone; /* "JST", "EST", "EDT", etc. */
29
+ uint16_t yday : 9; /* 1..366 */
30
+ uint8_t mon : 4; /* 1..12 */
31
+ uint8_t mday : 5; /* 1..31 */
32
+ uint8_t hour : 5; /* 0..23 */
33
+ uint8_t min : 6; /* 0..59 */
34
+ uint8_t sec : 6; /* 0..60 */
35
+ uint8_t wday : 3; /* 0:Sunday, 1:Monday, ..., 6:Saturday 7:init */
36
+ uint8_t isdst : 2; /* 0:StandardTime 1:DayLightSavingTime 3:init */
37
+ });
38
+ PACKED_STRUCT_UNALIGNED(struct time_object {
39
+ wideval_t timew; /* time_t value * TIME_SCALE. possibly Rational. */
40
+ struct vtm vtm;
41
+ uint8_t gmt : 3; /* 0:utc 1:localtime 2:fixoff 3:init */
42
+ uint8_t tm_got : 1;
43
+ });
44
+ #else
45
+ struct vtm {
46
+ VALUE year; /* 2000 for example. Integer. */
47
+ int mon; /* 1..12 */
48
+ int mday; /* 1..31 */
49
+ int hour; /* 0..23 */
50
+ int min; /* 0..59 */
51
+ int sec; /* 0..60 */
52
+ VALUE subsecx; /* 0 <= subsecx < TIME_SCALE. possibly Rational. */
53
+ VALUE utc_offset; /* -3600 as -01:00 for example. possibly Rational. */
54
+ int wday; /* 0:Sunday, 1:Monday, ..., 6:Saturday */
55
+ int yday; /* 1..366 */
56
+ int isdst; /* 0:StandardTime 1:DayLightSavingTime */
57
+ const char *zone; /* "JST", "EST", "EDT", etc. */
58
+ };
59
+ struct time_object {
60
+ wideval_t timew; /* time_t value * TIME_SCALE. possibly Rational. */
61
+ struct vtm vtm;
62
+ int gmt; /* 0:utc 1:localtime 2:fixoff */
63
+ int tm_got;
64
+ };
65
+ #endif
66
+
67
+ VALUE
68
+ rb_time_succ(VALUE time);
69
+ VALUE
70
+ rbtime_timespec_new(const struct timespec *ts, int offset)
71
+ {
72
+ VALUE obj = rb_time_nano_new(ts->tv_sec, ts->tv_nsec);
73
+ if (offset) {
74
+ struct time_object *tobj;
75
+ tobj = DATA_PTR(obj);
76
+ tobj->tm_got = 0;
77
+ tobj->gmt = 2;
78
+ tobj->vtm.utc_offset = INT2FIX(offset);
79
+ tobj->vtm.zone = NULL;
80
+ }
81
+ return obj;
82
+ }
83
+
84
+ /* timespec_now */
85
+ void
86
+ timespec_now(struct timespec *ts)
87
+ {
88
+ #ifdef HAVE_CLOCK_GETTIME
89
+ if (clock_gettime(CLOCK_REALTIME, ts) == -1) {
90
+ rb_sys_fail("clock_gettime");
91
+ }
92
+ #else
93
+ {
94
+ struct timeval tv;
95
+ if (gettimeofday(&tv, 0) < 0) {
96
+ rb_sys_fail("gettimeofday");
97
+ }
98
+ ts->tv_sec = tv.tv_sec;
99
+ ts->tv_nsec = tv.tv_usec * 1000;
100
+ }
101
+ #endif
102
+ }
103
+
104
+ /* localtime_with_gmtoff_zone */
105
+ #ifdef HAVE_GMTIME_R
106
+ #define rb_gmtime_r(t, tm) gmtime_r((t), (tm))
107
+ #define rb_localtime_r(t, tm) localtime_r((t), (tm))
108
+ #else
109
+ static inline struct tm *
110
+ rb_gmtime_r(const time_t *tp, struct tm *result)
111
+ {
112
+ struct tm *t = gmtime(tp);
113
+ if (t) *result = *t;
114
+ return t;
115
+ }
116
+
117
+ static inline struct tm *
118
+ rb_localtime_r(const time_t *tp, struct tm *result)
119
+ {
120
+ struct tm *t = localtime(tp);
121
+ if (t) *result = *t;
122
+ return t;
123
+ }
124
+ #endif
125
+
126
+ static struct tm *
127
+ rb_localtime_r2(const time_t *t, struct tm *result)
128
+ {
129
+ #if defined __APPLE__ && defined __LP64__
130
+ if (*t != (time_t)(int)*t) return NULL;
131
+ #endif
132
+ result = rb_localtime_r(t, result);
133
+ #if defined(HAVE_MKTIME) && defined(LOCALTIME_OVERFLOW_PROBLEM)
134
+ if (result) {
135
+ long gmtoff1 = 0;
136
+ long gmtoff2 = 0;
137
+ struct tm tmp = *result;
138
+ time_t t2;
139
+ #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
140
+ gmtoff1 = result->tm_gmtoff;
141
+ #endif
142
+ t2 = mktime(&tmp);
143
+ #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
144
+ gmtoff2 = tmp.tm_gmtoff;
145
+ #endif
146
+ if (*t + gmtoff1 != t2 + gmtoff2) result = NULL;
147
+ }
148
+ #endif
149
+ return result;
150
+ }
151
+ #define LOCALTIME(tm, result) (tzset(), rb_localtime_r2((tm), &(result)))
152
+
153
+ #if !defined(HAVE_STRUCT_TM_TM_GMTOFF)
154
+ static struct tm *
155
+ rb_gmtime_r2(const time_t *t, struct tm *result)
156
+ {
157
+ result = rb_gmtime_r(t, result);
158
+ #if defined(HAVE_TIMEGM) && defined(LOCALTIME_OVERFLOW_PROBLEM)
159
+ if (result) {
160
+ struct tm tmp = *result;
161
+ time_t t2 = timegm(&tmp);
162
+ if (*t != t2) result = NULL;
163
+ }
164
+ #endif
165
+ return result;
166
+ }
167
+ #define GMTIME(tm, result) rb_gmtime_r2((tm), &(result))
168
+ #endif
169
+
170
+ struct tm *
171
+ localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff,
172
+ const char **zone)
173
+ {
174
+ struct tm tm;
175
+
176
+ if (LOCALTIME(t, tm)) {
177
+ #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
178
+ *gmtoff = tm.tm_gmtoff;
179
+ #else
180
+ struct tm *u, *l;
181
+ long off;
182
+ struct tm tmbuf;
183
+ l = &tm;
184
+ u = GMTIME(t, tmbuf);
185
+ if (!u) return NULL;
186
+ if (l->tm_year != u->tm_year)
187
+ off = l->tm_year < u->tm_year ? -1 : 1;
188
+ else if (l->tm_mon != u->tm_mon)
189
+ off = l->tm_mon < u->tm_mon ? -1 : 1;
190
+ else if (l->tm_mday != u->tm_mday)
191
+ off = l->tm_mday < u->tm_mday ? -1 : 1;
192
+ else
193
+ off = 0;
194
+ off = off * 24 + l->tm_hour - u->tm_hour;
195
+ off = off * 60 + l->tm_min - u->tm_min;
196
+ off = off * 60 + l->tm_sec - u->tm_sec;
197
+ *gmtoff = off;
198
+ #endif
199
+
200
+ *result = tm;
201
+ return result;
202
+ }
203
+ return NULL;
204
+ }
205
+
206
+ #define NDIV(x,y) (-(-((x)+1)/(y))-1)
207
+ #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
208
+
209
+ static int
210
+ leap_year_p(int y)
211
+ {
212
+ return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0);
213
+ }
214
+
215
+ static const int common_year_yday_offset[] = {
216
+ -1,
217
+ -1 + 31,
218
+ -1 + 31 + 28,
219
+ -1 + 31 + 28 + 31,
220
+ -1 + 31 + 28 + 31 + 30,
221
+ -1 + 31 + 28 + 31 + 30 + 31,
222
+ -1 + 31 + 28 + 31 + 30 + 31 + 30,
223
+ -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31,
224
+ -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
225
+ -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
226
+ -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
227
+ -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
228
+ /* 1 2 3 4 5 6 7 8 9 10 11 */
229
+ };
230
+ static const int leap_year_yday_offset[] = {
231
+ -1,
232
+ -1 + 31,
233
+ -1 + 31 + 29,
234
+ -1 + 31 + 29 + 31,
235
+ -1 + 31 + 29 + 31 + 30,
236
+ -1 + 31 + 29 + 31 + 30 + 31,
237
+ -1 + 31 + 29 + 31 + 30 + 31 + 30,
238
+ -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31,
239
+ -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
240
+ -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
241
+ -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
242
+ -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
243
+ /* 1 2 3 4 5 6 7 8 9 10 11 */
244
+ };
245
+
246
+ static const int common_year_days_in_month[] = {
247
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
248
+ };
249
+ static const int leap_year_days_in_month[] = {
250
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
251
+ };
252
+
253
+ time_t
254
+ timegm_noleapsecond(struct tm *tm)
255
+ {
256
+ long tm_year = tm->tm_year;
257
+ int tm_yday = tm->tm_mday;
258
+ if (leap_year_p(tm_year + 1900))
259
+ tm_yday += leap_year_yday_offset[tm->tm_mon];
260
+ else
261
+ tm_yday += common_year_yday_offset[tm->tm_mon];
262
+
263
+ /*
264
+ * `Seconds Since the Epoch' in SUSv3:
265
+ * tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
266
+ * (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
267
+ * ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
268
+ */
269
+ return tm->tm_sec + tm->tm_min*60 + tm->tm_hour*3600 +
270
+ (time_t)(tm_yday +
271
+ (tm_year-70)*365 +
272
+ DIV(tm_year-69,4) -
273
+ DIV(tm_year-1,100) +
274
+ DIV(tm_year+299,400))*86400;
275
+ }
276
+
277
+ void
278
+ tm_add_offset(struct tm *tm, long diff)
279
+ {
280
+ int sign, tsec, tmin, thour, tday;
281
+
282
+ if (diff < 0) {
283
+ sign = -1;
284
+ diff = -diff;
285
+ }
286
+ else {
287
+ sign = 1;
288
+ }
289
+ tsec = diff % 60;
290
+ diff = diff / 60;
291
+ tmin = diff % 60;
292
+ diff = diff / 60;
293
+ thour = diff % 24;
294
+ diff = diff / 24;
295
+
296
+ if (sign < 0) {
297
+ tsec = -tsec;
298
+ tmin = -tmin;
299
+ thour = -thour;
300
+ }
301
+
302
+ tday = 0;
303
+
304
+ if (tsec) {
305
+ tsec += tm->tm_sec;
306
+ if (tsec < 0) {
307
+ tsec += 60;
308
+ tmin -= 1;
309
+ }
310
+ if (60 <= tsec) {
311
+ tsec -= 60;
312
+ tmin += 1;
313
+ }
314
+ tm->tm_sec = tsec;
315
+ }
316
+
317
+ if (tmin) {
318
+ tmin += tm->tm_min;
319
+ if (tmin < 0) {
320
+ tmin += 60;
321
+ thour -= 1;
322
+ }
323
+ if (60 <= tmin) {
324
+ tmin -= 60;
325
+ thour += 1;
326
+ }
327
+ tm->tm_min = tmin;
328
+ }
329
+
330
+ if (thour) {
331
+ thour += tm->tm_hour;
332
+ if (thour < 0) {
333
+ thour += 24;
334
+ tday = -1;
335
+ }
336
+ if (24 <= thour) {
337
+ thour -= 24;
338
+ tday = 1;
339
+ }
340
+ tm->tm_hour = thour;
341
+ }
342
+
343
+ if (tday) {
344
+ if (tday < 0) {
345
+ if (tm->tm_mon == 1 && tm->tm_mday == 1) {
346
+ tm->tm_mday = 31;
347
+ tm->tm_mon = 12; /* December */
348
+ tm->tm_year = tm->tm_year - 1;
349
+ }
350
+ else if (tm->tm_mday == 1) {
351
+ const int *days_in_month = leap_year_p(tm->tm_year)
352
+ ? leap_year_days_in_month
353
+ : common_year_days_in_month;
354
+ tm->tm_mon--;
355
+ tm->tm_mday = days_in_month[tm->tm_mon - 1];
356
+ }
357
+ else {
358
+ tm->tm_mday--;
359
+ }
360
+ }
361
+ else {
362
+ int leap = leap_year_p(tm->tm_year);
363
+ if (tm->tm_mon == 12 && tm->tm_mday == 31) {
364
+ tm->tm_year = tm->tm_year + 1;
365
+ tm->tm_mon = 1; /* January */
366
+ tm->tm_mday = 1;
367
+ }
368
+ else if (tm->tm_mday ==
369
+ (leap ? leap_year_days_in_month
370
+ : common_year_days_in_month)[tm->tm_mon - 1]) {
371
+ tm->tm_mon++;
372
+ tm->tm_mday = 1;
373
+ }
374
+ else {
375
+ tm->tm_mday++;
376
+ }
377
+ }
378
+ }
379
+ }
380
+