文字列型日時ののN秒後時間取得
最近は普通にパーサがある時代になったのですね。 ごめんなさい盲点でした^^;; ということで、「仕様.3」については、 入力の書式は限定しないこととし、出力の書式を限定するようにしてください。
Posted feedbacks - Nested
Flatten Hiddenこのお題は日時のparseをさせたいのでしょうか?それとも差分の計算をさせたいのでしょうか?
1 2 3 4 5 6 7 | def dateex(d, delta):
return d + datetime.timedelta(seconds=delta)
if __name__ == '__main__':
import time
day = datetime.date(2008, 8, 31)
print dateex(day, 100000)
|
ども、raynstardです。 うーん、どっちにになるのでしょう?(笑 このお題の目的は、文字列という日付とは関係ない入力データで 日付の計算をすることです。 そもそもの発端は、シェルで自分自身を 再スケジュールしようとしたらシェルじゃできねぇってことで 計算部分をperlの呼び出しで妥協してしまったことです。 最近の言語には、大抵パーサがあるのですね。 盲点でしたorz
addSeconds = 40
> "2008/08/28 00:00:05"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | using System;
class Program {
static void Main(string[] args) {
Console.WriteLine(
DateEx(Console.ReadLine(), long.Parse(Console.ReadLine()))
);
Console.WriteLine(
DateEx(long.Parse(Console.ReadLine()))
);
Console.ReadLine();
}
static string DateEx(string date, long addSeconds) {
DateTime d;
DateTime.TryParse(date, out d);
if(d == null) throw new ArgumentException("日付が正しくありません。", "date");
return d.AddSeconds((double)addSeconds).ToString();
}
static string DateEx(long addSeconds) {
return DateEx(DateTime.Now.ToString(), addSeconds);
}
}
|
1 2 3 4 | <?php
function DateEx($time, $diff){
echo echo date('YmdHis',strtotime($time)+$diff);
}
|
echoが2つになってしまった・・・。片方いらないです。
1 2 3 | DateEx() {
date -d "$1 $2 seconds"
}
|
仕様2を満たしていませんでした。
修正と、ついでに1引数に対応。
1 2 3 4 5 6 7 8 | DateEx() {
[ -z "$2" ] && set '' $1
if [[ $2 == -* ]];then
date -d "$1 ${2:1} seconds ago"
else
date -d "$1 $2 seconds"
fi
}
|
てもとのdateコマンドでは動きませんでした。 バージョンていくつでしょう? $ date --version date (GNU coreutils) 5.96 Copyright (C) 2006 Free Software Foundation, Inc. This is free software. You may redistribute copies of it under the terms of the GNU General Public License <http://www.gnu.org/licenses/gpl.html>. There is NO WARRANTY, to the extent permitted by law. Written by David MacKenzie.
なるほど、少なくともcoreutils版dateじゃないと使えないんですね。
私のところでの実行例は以下のとおりです。
$ DateEx 'Thu Aug 28 23:59:25 JST 2008' 40
Fri Aug 29 00:00:05 JST 2008
あれ?バージョン同じだぞ?とおもって再度やってみたら動きました。 秒の指定を間違えていたみたいです。 失礼しました。
入出力の日付文字列はISO8601形式です。
see: "XQuery 1.0 and XPath 2.0 Functions and Operators" の日付関連の説明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:my="uri:ja.doukaku.org:my-functions"
exclude-result-prefixes="my"
>
<xsl:output method="text" />
<xsl:template match="/" >
<xsl:value-of select="my:DateEx('2008-09-01T10:02:38', 10000)"/>
</xsl:template>
<xsl:function name="my:DateEx" as="xs:string">
<xsl:param name="dstr" as="xs:string" />
<xsl:param name="sec" as="xs:integer" />
<xsl:sequence select="xs:string(
xs:dateTime($dstr) +
xs:dayTimeDuration(fn:concat('PT',xs:string($sec),'S'))
)" />
</xsl:function>
</xsl:stylesheet>
|
条件2を満たしてなかった。ので、修正。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:my="uri:ja.doukaku.org:my-functions"
exclude-result-prefixes="my"
>
<xsl:output method="text" />
<xsl:template match="/" >
<xsl:value-of select="my:DateEx('2008-09-01T10:02:38', -1)"/>
</xsl:template>
<xsl:function name="my:DateEx" as="xs:string">
<xsl:param name="dstr" as="xs:string" />
<xsl:param name="sec" as="xs:integer" />
<xsl:sequence select="xs:string(
xs:dateTime($dstr) +
xs:dayTimeDuration(
fn:concat(
(if($sec<0)then'-'else''),
'PT', xs:string(fn:abs($sec)), 'S'
)
)
)" />
</xsl:function>
</xsl:stylesheet>
|
フォーマットの指定がなかったので、とりあえずサンプルと同じにしてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Sample204 {
private static final DateFormat FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
public static String dateEx(String time, int seconds) throws ParseException {
Date date = FORMAT.parse(time);
return dateEx(date, seconds);
}
public static String dateEx(int seconds) {
return dateEx(new Date(), seconds);
}
private static String dateEx(Date date, int seconds) {
Calendar cal = Calendar.getInstance();
cal.setTime( date );
cal.add(Calendar.SECOND, seconds);
return FORMAT.format(cal.getTime());
}
public static void main(String[] args) {
try {
System.out.println(dateEx("20080827235925",40));
System.out.println(dateEx(0));
} catch (ParseException ex) {
ex.printStackTrace();
}
}
}
|
DateTimeと関連モジュールを使って。 入力はコマンドライン引数で、ISO8601形式の日付と秒数を指定します。 日付を省略すると実行時の時刻を使います。 # 入力はISO8601形式じゃなくてもparseしてくれます。ので、お題の条件3.が微妙な感じ
see: DateTime::Format::DateParse
1 2 3 4 5 6 7 8 9 | use strict;
use warnings;
use DateTime;
use DateTime::Format::DateParse;
my $d = @ARGV==2 ? DateTime::Format::DateParse->parse_datetime(shift)
: DateTime->now(time_zone => q{Asia/Tokyo});
print $d->add(seconds => shift||0)->iso8601,$/;
|
しまった、お題は「関数を作れ」だった。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | use strict;
use warnings;
use DateTime;
use DateTime::Format::DateParse;
print DateEx(@ARGV),$/;
sub DateEx
{
(@_>=2 ? DateTime::Format::DateParse->parse_datetime(shift)
: DateTime->now(time_zone => q{Asia/Tokyo}))
->add(seconds => shift||0)->iso8601;
}
|
Perlにまでパーサっがあったのですね。。。 僕が妥協した時はPOSIXを使ったべた書きでした。 # ほとんどCとかわりません(笑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/env perl
use strict;
use POSIX qw/strftime mktime/;
sub DateEx($$)
{
my $outDate = '';
my @t = ($_[0] =~ m/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/);
$t[0] -= 1900; $t[1] -= 1; @t = reverse @t;
$t[0] += $_[1];
mktime( @t );
return strftime("%Y%m%d%H%M%S", @t);
}
print DateEx("20080827235925",40) . "\n";
__END__
#EOF
|
Boost.Date_Time で。 入出力の日付形式はコード中に書いてある通り(例:"2008-Sep-01 12:34:56")です。
see: Boost.Date_Time
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include <iostream>
#include <string>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lexical_cast.hpp>
std::string
DateEx(
const std::string& dstr,
int sec
)
{
using namespace boost::posix_time;
return boost::lexical_cast<std::string>(
ptime(dstr.empty() ? second_clock::local_time()
: time_from_string(dstr)
) + seconds(sec)
);
}
int main(int c, char** v)
{
if ( c == 1 ) {
std::cout << "usage: " << v[0] << " [<datetime{YYYY-Mon-DD hh:mm:ss}>] <seconds>\n";
return 0;
}
std::cout << DateEx(
c>=3?v[1]:"",
boost::lexical_cast<int>(c>=3?v[2]:v[1])
) << "\n";
return 0;
}
|
Squeak Smalltalk では日時オブジェクト同士の演算が可能です。
1 2 3 4 5 | "文字列指定した日時の場合"
'2008-09-01T12:00:00+09:00' asDateAndTime - 10 seconds "=> 2008-09-01T11:59:50+09:00 "
"現在日時の場合"
DateAndTime now + 15 seconds
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import std.conv;
import std.date;
import std.stdio;
string DateEx(string datetime, int tdelta_in_secs)
{
d_time t = std.date.parse(datetime);
d_time new_datetime = t + tdelta_in_secs * std.date.TicksPerSecond;
return std.date.toString(new_datetime);
}
void main(string[] args)
{
string datetime;
int tdelta_in_secs;
if (args.length == 3) {
datetime = args[1];
tdelta_in_secs = toInt(args[2]);
}
else {
d_time now = std.date.getUTCtime;
datetime = std.date.toString(now);
tdelta_in_secs = toInt(args[1]);
}
writefln("%s", DateEx(datetime, tdelta_in_secs));
}
// eof
|
使用例も書かないとダメですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | import std.conv;
import std.date;
import std.stdio;
string DateEx(string datetime, int tdelta_in_secs)
{
d_time t = std.date.parse(datetime);
d_time new_datetime = t + tdelta_in_secs * std.date.TicksPerSecond;
return std.date.toString(new_datetime);
}
unittest {
assert(DateEx("Mon Sep 01 13:00:00 GMT+0900 2008", -3600) ==
"Mon Sep 01 12:00:00 GMT+0900 2008");
assert(DateEx("Mon Sep 01 13:00:00 GMT+0900 2008", 3600) ==
"Mon Sep 01 14:00:00 GMT+0900 2008");
}
void main(string[] args)
{
string datetime;
int tdelta_in_secs;
if (args.length == 3) {
datetime = args[1];
tdelta_in_secs = toInt(args[2]);
}
else {
d_time now = std.date.getUTCtime;
datetime = std.date.toString(now);
tdelta_in_secs = toInt(args[1]);
}
writefln("%s", DateEx(datetime, tdelta_in_secs));
}
// eof
|
3.の条件を無視すればこれでもOKです。 (Time.parseはさまざまな書式を受け付けるため) def date_ex(diff, date = Time.now.to_s) puts Time.parse(date) + diff end
1 2 3 4 5 6 7 8 9 | require 'time'
def date_ex(diff, date = Time.now.strftime("%Y/%m/%d %H:%M:%S"))
raise unless date =~ /\d+\/\d+\/\d+\s+\d+:\d+:\d+/
puts (Time.parse(date) + diff).strftime("%Y/%m/%d %H:%M:%S")
end
date_ex(100, '2008/09/01 14:06:25') #=> 2008/09/01 14:08:05
date_ex(100) #=> 「現在時刻」から100秒後
|
VBA for Excel (2003)
1 2 3 4 | Function DateEx(str, sec)
p = InStr(str, " ")
DateEx = DateValue(Left(str, p - 1)) + TimeValue(Right(str, Len(str) - p)) + sec / 86400
End Function
|
関数に出力機能まで含めるとなんか使いにくそう。 '2008 8 27 23 59 25' DateEx 40 2008 8 28 0 0 5 '2008 8 27 23 59 25' DateEx _40 2008 8 27 23 58 45 DateEx 100000000 2011 11 3 0 12 46.731
1 2 3 4 5 6 7 8 9 | load 'dates'
now =: 6!:0
DateEx =: 3 : 0
(": now '') DateEx y
:
wd 1 tsrep (y * 1000) + tsrep ". x
)
|
日時の書式は ISO-8601 の「西暦-月-日T時:分:秒」形式です。時間を省略する場合には空文字列を渡すことにしてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | (use srfi-13)
(use srfi-19)
(define (date-ex str delta)
(let ((t (if (string-null? str)
(current-time time-utc)
(date->time-utc
(string->date str "~Y-~m-~dT~H:~M:~S")))))
(date->string
(time-utc->date
(add-duration t (make-time time-duration 0 delta)))
"~5")))
(define (main args)
(print (date-ex (cadr args) (string->number (caddr args)))))
|
他にも様々な形式をパーズしてくれるライブラリです。
CLの引数の順番はお題の例とは逆にしています。
(date-ex 40 "Thu, 28 Aug 2007 23:59:25 +0900")
;=> "Thu, 30 Aug 2007 00:00:05 +0900"
(date-ex -3600)
;=> "Mon, 01 Sep 2008 17:56:51 +0900"
see: net-telent-date
1 2 3 4 5 6 7 8 9 10 11 | (require :net-telent-date)
(require :lw-compat)
(defpackage :doukaku-204 (:use :cl :date :lispworks))
(in-package :doukaku-204)
(defun date-ex (sec &optional time-string)
(when-let (ut (if time-string
(parse-time time-string)
(get-universal-time)))
(universal-time-to-rfc2822-date (+ ut sec))))
|
フォーマットが任意だと楽ちんでいいですね。
> DateEx("2008-09-02 00:00:00 JST", 30)
[1] "2008-09-02 00:00:30 JST"
> DateEx("2008-09-02 00:00:00 JST", -30)
[1] "2008-09-01 23:59:30 JST"
1 2 3 | DateEx <- function(d1=Sys.time(), d2=0){
as.POSIXct(d1) + d2
}
|
Javaと余り変わりませんがscala版を。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import java.text.DateFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
object DateEx {
val formatter:DateFormat = new SimpleDateFormat("yyyyMMddHHmmss")
def DateEx(date:String,diff:Int):String = {
val calendar:Calendar = Calendar.getInstance
calendar.setTime(formatter.parse(date))
DateEx(calendar,diff)
}
def DateEx(diff:Int):String = DateEx(Calendar.getInstance,diff)
def DateEx(calendar:Calendar,diff:Int):String = {
calendar.add(Calendar.SECOND,diff)
formatter.format(calendar.getTime)
}
def main(args:Array[String]):Unit = {
try {
args.length match {
case 2 => println(DateEx(args(0),args(1).toInt))
case 1 => println(DateEx(args(0).toInt))
case _ => println(DateEx("20080827235925",40))
}
} catch {
case ex:ParseException => println("invalid date format.")
case ex => ex.printStackTrace
}
}
}
|
出力形式にあわせるとこんな入力になった。
toLocaleStringメソッドを使えば"2008年9月2日 8:50:34"のように出力するが、パーサが解釈してくれない。
>>> DateEx('Tue Sep 02 2008 8:30:00',1234)
"Tue Sep 02 2008 08:50:34 GMT+0900"
1 | function DateEx(t,s) new Date(Date.parse(t)+s*1000).toString();
|
こんなのもあたーよ。
see: dateformat.js
なんの工夫もないコードです。
1 2 3 4 5 6 7 | import Data.Time
addDate time sec = show $ addUTCTime sec $ read time
main = do
putStrLn $ addDate "2008-09-02 10:20:30 UTC" 15
putStrLn $ addDate "2008-09-02 10:20:30 UTC" (-5)
|
なでしこで。下の二つの関数はほかから流用です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | DateEx("2008/08/27 23:59:25",40)を表示
DateEx("2008/08/27",40)を表示
●DateEx(str,n)
dateとは配列=区切(str," ")
もし(date[1]="")ならば、date[1]=今
配列結合(UNIX2date(date2UNIX(date,0)+n)," ")
●date2UNIX(date,tzd)
戻(日数差("1970/1/1",date[0])*(60*60*24)+秒差("0:0:0",date[1])+tzd)
●UNIX2date(unix)
tmpとは配列
dayとは整数=unix/86400%86400
unix=unix-day*86400
tmp[0]=日付加算("1970/1/1","//{day}")
tmp[1]="{ゼロ埋め(unix/3600%24,2)}:{ゼロ埋め(unix/60%60,2)}:{ゼロ埋め(unix%60,2)}"
tmpで戻る
|
モジュールなしで書いた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | #! /usr/bin/perl
use strict;
use warnings;
my $date_string = 20080827235925;
my $add_seconds = 40;
print DateEx($date_string,$add_seconds);
sub DateEx{
my ($date_string, $add_seconds) = @_;
return 'Error!' unless $date_string =~ /^\d{14}$/;
return 'Error!' unless $add_seconds =~ /^-?\d+$/;
my ($year,$month,$day,$hour,$minutes,$seconds)
= $date_string =~ /^(\d{1,4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/;
my @result = add_seconds($year,$month,$day,$hour,$minutes,$seconds,$add_seconds);
return sprintf("%04d%02d%02d%02d%02d%02d",@result);
}
sub add_seconds{
my ($year,$month,$day,$hour,$minutes,$seconds,$add_seconds) = @_;
#時間、秒を先に出す
my ($tmp_day,$result_hour,$result_minutes,$result_seconds)
= seconds_to_day($add_seconds + day_to_seconds($day-1,$hour,$minutes,$seconds));
#日付を計算
my ($result_year, $result_month, $result_day)
= date_add($year,$month,$tmp_day);
return ($result_year,$result_month,$result_day,$result_hour,$result_minutes,$result_seconds);
}
sub day_to_seconds{#何日、何時間、何分の形式を総秒数に変換
my ($day,$hour,$minutes,$seconds) = @_;
my $SECONDS_PER_MINUTES = 60;
my $SECONDS_PER_HOUR = $SECONDS_PER_MINUTES * 60;
my $SECONDS_PER_DAY = $SECONDS_PER_HOUR * 24;
my $total_second = $day * $SECONDS_PER_DAY
+ $hour * $SECONDS_PER_HOUR
+ $minutes * $SECONDS_PER_MINUTES
+ $seconds
;
return $total_second;
}
sub seconds_to_day{#秒数を 何日、何時間、何分の形式に変換
my ($total_seconds) = @_;
my $SECONDS_PER_MINUTES = 60;
my $SECONDS_PER_HOUR = $SECONDS_PER_MINUTES * 60;
my $SECONDS_PER_DAY = $SECONDS_PER_HOUR * 24;
my ($day,$hour,$minutes,$seconds) = (0,0,0,0);
if($total_seconds > 0){
$day = int($total_seconds / $SECONDS_PER_DAY) + 1;
$hour = int($total_seconds / $SECONDS_PER_HOUR) % 24;
$minutes = int($total_seconds / $SECONDS_PER_MINUTES) % 60;
$seconds = $total_seconds % 60;
}
elsif($total_seconds < 0){
$day = (int(($total_seconds * (-1))/$SECONDS_PER_DAY) + 1) * (-1);
$total_seconds += $day * $SECONDS_PER_DAY * (-1);
$hour = int($total_seconds / $SECONDS_PER_HOUR) % 24;
$minutes = int($total_seconds / $SECONDS_PER_MINUTES) % 60;
$seconds = $total_seconds % 60;
}
return ($day,$hour,$minutes,$seconds);
}
sub date_add{#2008年8月33日は2008年9月2日のような考え方
my ($year,$month,$day) = @_;
#400年以上のスパンがある場合
while(abs($day) > (my $DAYS_IN_400YEARS = 365*400+97)){
if($day > 0){
$day -= $DAYS_IN_400YEARS;
$year += 400;
}
else{
$day += $DAYS_IN_400YEARS;
$year -= 400;
}
}
#1年以上のスパンがある場合
while(abs($day) > 366){
if($day > 0){
if($month <= 2){
while($day > 366){
_uru_or_not($year) ? $day -= 366 : $day -= 365;
$year++;
}
}
else{
while($day > 366){
_uru_or_not($year+1) ? $day -= 366 : $day -= 365;
$year++;
}
}
}
else{
if($month <= 2){
while($day < -366){
_uru_or_not($year-1) ? $day += 366 : $day += 365;
$year--
}
}
else{
while($day < -366){
_uru_or_not($year) ? $day += 366 : $day += 365;
$year--
}
}
}
}
#一月づつ、足すもしくはさかのぼる
while(!(($day > 0) && (_get_days_of_month($year,$month) >= $day))){
if($day > 0){
$day -= _get_days_of_month($year,$month);
$month++;
if($month == 13){
$year++;
$month = 1;
}
}
else{
$month--;
if($month == 0){
$year--;
$month = 12;
}
$day += (_get_days_of_month($year,$month) + 1);
}
}
return ($year,$month,$day);
}
sub _uru_or_not{#閏年か否かの判定
my ($year) = @_;
return 1 if($year % 400 == 0);
return 0 if($year % 100 == 0);
return 1 if($year % 4 == 0);
return 0;
}
sub _get_days_of_month{#年と月を与えるとその日数を返す
my ($year,$month) = @_;
my @days_of_months = qw{0 31 28 31 30 31 30 31 31 30 31 30 31};
if(($month == 2) && (_uru_or_not($year))){
return 29;
}
return $days_of_months[$month];
}
|
初めて投稿します。よろしくお願いします。new Date(String s)を使えばもっと短く書けると思うけど、deprecatedだから反則ですよね...
1 2 3 4 5 6 7 8 9 | format = new java.text.SimpleDateFormat('yyyyMMddHHmmss')
def dateEx(delta, date = null) {
d = (date) ? format.parse(date) : new Date()
format.format(new Date(d.time + delta * 1000))
}
println dateEx(40, "20080827235925")
println dateEx(100)
|
see: レコードの名前空間 - みずぴー日記
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #load "unix.cma";;
let scan_time s =
Scanf.sscanf s "%4d%2d%2d%2d%2d%2d" (fun year mon day h m s ->
{ Unix.tm_sec = s; tm_min = m; tm_hour = h;
tm_mday = day; tm_mon = mon; tm_year = year-1900;
tm_wday = 0; tm_yday = 0; tm_isdst = false
} ) ;;
let print_time {
tm_year = yy; tm_mon = mm; tm_mday = dd;
tm_hour = h; tm_min = m; Unix.tm_sec = s } =
Printf.printf "%d%02d%02d%02d%02d%02d" (yy+1900) mm dd h m s;;
let date_ex s sec =
let {Unix.tm_sec = tsec} as tm = scan_time s in
print_time (snd (Unix.mktime {tm with Unix.tm_sec=tsec+sec}));;
(* date_ex "20080827235925" 40;; *)
|
PostScript で。 すっかり泥沼化してしまったので、まだバグがあるかもしれません。 対応は日本時間のみで、1970-2050年に対応。 ただし、2009年7月1日以降、1/1, 7/1 の午前9時を含む計算で各1秒のずれが 生じる可能性があります(仕様)。 (20080927000010) -40 DateEx ==> (20080926235930) (20080101085900) 60 DateEx ==> (20080101090000) (20080101085900) 120 DateEx ==> (20080101090100) (20090101085900) 60 DateEx ==> (20090101085960) (うるう秒) (20090101085900) 120 DateEx ==> (20090101090059) (うるう秒)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | %!PS
/JST 9 60 60 mul mul def
/LDAY 24 60 60 mul mul def
/MOFF [
0 31 dup 28 add dup 31 add dup 30 add dup 31 add dup 30 add dup 31 add
dup 31 add dup 30 add dup 31 add dup 30 add dup 31 add
] def
/StrToUTC0 { % (Date String) StrToUTC MJD UTC_L
% Get UTC / Ignore TZ & leap secs.
dup 8 2 getinterval cvi 3600 mul exch
dup 10 2 getinterval cvi 60 mul exch
dup 12 2 getinterval cvi exch
4 1 roll add add
exch
dup 0 4 getinterval cvi exch
dup 4 2 getinterval cvi
dup 2 le {
3 -1 roll 1 sub 3 1 roll
12 add
} if
exch
6 2 getinterval cvi
exch 2 sub 30.59 mul cvi
add exch
dup 365.25 mul cvi exch
dup 400 div cvi exch
100 div cvi sub add add
678912 sub
exch
} bind def
/LeapSecs0 [
[ (19720630235960) StrToUTC0 ]
[ (19721231235960) StrToUTC0 ]
[ (19731231235960) StrToUTC0 ]
[ (19741231235960) StrToUTC0 ]
[ (19751231235960) StrToUTC0 ]
[ (19761231235960) StrToUTC0 ]
[ (19771231235960) StrToUTC0 ]
[ (19781231235960) StrToUTC0 ]
[ (19791231235960) StrToUTC0 ]
[ (19810630235960) StrToUTC0 ]
[ (19820630235960) StrToUTC0 ]
[ (19830630235960) StrToUTC0 ]
[ (19850630235960) StrToUTC0 ]
[ (19871231235960) StrToUTC0 ]
[ (19891231235960) StrToUTC0 ]
[ (19901231235960) StrToUTC0 ]
[ (19920630235960) StrToUTC0 ]
[ (19930630235960) StrToUTC0 ]
[ (19940630235960) StrToUTC0 ]
[ (19951231235960) StrToUTC0 ]
[ (19970630235960) StrToUTC0 ]
[ (19981231235960) StrToUTC0 ]
[ (20051231235960) StrToUTC0 ]
[ (20081231235960) StrToUTC0 ]
] def
/LeapSecs 30 dict def
LeapSecs0 {
LeapSecs exch aload pop put
} forall
/IsLeapDay { % MJD IsLeapDay bool
LeapSecs exch known
} bind def
/Normalize { % MJD secs Normalize MJD' secs'
{
dup 0 lt {
LDAY add
exch 1 sub exch
LeapSecs 2 index known { 1 add } if
} {
dup LDAY eq {
LeapSecs 2 index known { exit } if
} if
dup LDAY lt {
exit
} if
LeapSecs 2 index known {
1 sub
} if
LDAY sub
exch 1 add exch
} ifelse
} loop
} bind def
/StrToUTC { % (Date String) StrToUTC MJD secs
dup
StrToUTC0
JST sub
% (Date) MJD secs'
dup 0 lt {
exch 1 sub exch LDAY add
} if
dup 0 eq {
1 index 1 sub IsLeapDay
{
2 index 8 6 getinterval (085960) eq
{
exch 1 sub exch LDAY add
} if
} if
} if
Normalize
3 -1 roll pop
} bind def
/cvs2 { % int cvs2 (dd)
2 string dup dup 3 index
% int () ()
10 idiv 1 string cvs 0 exch putinterval
3 -1 roll 10 mod 1 string cvs 1 exch putinterval
} bind def
/CompTime {
% MJD sec () MJD' sec' CompTime MJD sec () -1/0/1
% LocalFunction
3 index sub exch
4 index sub
% MJD sec () sec'' MJD''
dup 0 lt {
pop pop -1
} {
0 gt {
pop 1
}{
dup 0 lt {
pop -1
} {
0 gt {
1
} {
0
} ifelse
} ifelse
} ifelse
} ifelse
} bind def
/UTCToStr { % MJD secs UTCToStr (Date String)
14 string dup 0 (20080101000000) putinterval
2050 -1 1970 {
4 string cvs 1 index 0 3 -1 roll putinterval
dup StrToUTC CompTime
0 le { exit } if
} for
12 -1 1 {
cvs2 1 index 4 3 -1 roll putinterval
dup StrToUTC CompTime
0 le { exit } if
} for
31 -1 1 {
cvs2 1 index 6 3 -1 roll putinterval
dup StrToUTC CompTime
0 le { exit } if
} for
23 -1 0 {
cvs2 1 index 8 3 -1 roll putinterval
dup StrToUTC CompTime
0 le { exit } if
} for
% MJD secs (Date)
dup StrToUTC exch pop
% MJD secs (Date) secs'
4 2 roll exch pop sub neg
% (Date) secs
dup 3600 eq { % leap second
pop dup 10 (5960) putinterval
} {
dup 60 idiv
% (Date) secs min
cvs2 2 index 10 3 -1 roll putinterval
% (Date) secs
60 mod cvs2 1 index 12 3 -1 roll putinterval
} ifelse
} bind def
/DateEx { % (Date String) secs DateEx (New Date String)
exch StrToUTC
3 -1 roll add
Normalize
UTCToStr
} bind def
% =========================================================
% Test Code
(20080927000010) -40 DateEx ==
(20080101085900) 60 DateEx ==
(20080101085900) 120 DateEx ==
(20090101085900) 60 DateEx ==
(20090101085900) 120 DateEx ==
|
これはUnixタイムへの統一を行うと簡単にデータを加工(秒単位で追加)できます。 問題は一番面倒な文字列からUnixタイムの作成、Unixタイムから文字列の作成です。 時間の構造体やtime_tを使ってUnixタイムを実現しました。 面倒で雑ですが、一応汎用的な使い方ができるようにしています。
これはT216という独自ソフトウェアの作成の一貫として作ったコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | #include <time.h>
#include <stdio.h>
/* どう書く.org #7401
http://ja.doukaku.org/204/ */
time_t str_time(char *t)
{
struct tm tm;
time_t tt;
char s[5];
int i;
strncpy(s, t, 4);
i = atoi(s);
tm.tm_year = i - 1900;
s[2] = 0;
strncpy(s, t + 4, 2);
i = atoi(s);
tm.tm_mon = i - 1;
strncpy(s, t + 6, 2);
i = atoi(s);
tm.tm_mday = i - 1;
strncpy(s, t + 8, 2);
i = atoi(s);
tm.tm_hour = i;
strncpy(s, t + 10, 2);
i = atoi(s);
tm.tm_min = i;
strncpy(s, t + 12, 2);
i = atoi(s);
tm.tm_sec = i;
tt = mktime(&tm);
return tt;
}
void time_str(time_t tt, char *s)
{
struct tm *tp;
char sc[5];
tp = localtime(&tt);
sprintf(sc, "%d", tp->tm_year + 1900);
strcpy(s, sc);
sprintf(sc, "%02d", tp->tm_mon + 1);
strcat(s, sc);
sprintf(sc, "%02d", tp->tm_mday + 1);
strcat(s, sc);
sprintf(sc, "%02d", tp->tm_hour);
strcat(s, sc);
sprintf(sc, "%02d", tp->tm_min);
strcat(s, sc);
sprintf(sc, "%02d", tp->tm_sec);
strcat(s, sc);
return;
}
void org_7401(char *t, int n)
{
time_t tm;
tm = str_time(t);
tm += (time_t) n;
time_str(tm, t);
return;
}
int main(void)
{
char *s = malloc(15);
strcpy(s, "20080827235925");
org_7401(s, 40);
printf("%s\n", s);
free(s);
return 0;
}
|
適当だけど、こんな感じで良くない? それに、 tm.tm_isdst = 0; を忘れていたし、 tm.tm_mday = i - 1; は-1する必要がないので、答え間違っていたよ(汗 (書式にセパレートとかがあるとstrptimeとかも使えることがあるよ。)
see: ファイヤープロジェクト
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include <time.h>
#include <stdio.h>
/* どう書く.org #7401
http://ja.doukaku.org/204/ */
time_t str_time(char *t)
{
struct tm tm;
/* strptime(t,"%Y%m%d%H%M%S",&tm);*/
sscanf(t, "%04d%02d%02d%02d%02d%02d",
&tm.tm_year,
&tm.tm_mon,
&tm.tm_mday,
&tm.tm_hour,
&tm.tm_min,
&tm.tm_sec);
tm.tm_year -= 1900;
tm.tm_mon--;
tm.tm_isdst = 0;
return mktime(&tm);
}
void time_str(time_t tt, char *s)
{
struct tm *tp;
tp = localtime(&tt);
strftime(s, 15, "%Y%m%d%H%M%S", tp);
return;
}
void org_7401(char *t, int n)
{
time_t tm;
tm = str_time(t);
tm += (time_t) n;
time_str(tm, t);
return;
}
int main(void)
{
char *s = malloc(15);
strcpy(s, "20080827235925");
org_7401(s, 40);
puts(s);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include <time.h>
#include <stdio.h>
/* どう書く.org #7401
http://ja.doukaku.org/204/ */
time_t str_time(char *t)
{
struct tm tm;
// strptime(t,"%Y%m%d%H%M%S",&tm);
sscanf(t, "%04d%02d%02d%02d%02d%02d",
&tm.tm_year,
&tm.tm_mon,
&tm.tm_mday,
&tm.tm_hour,
&tm.tm_min,
&tm.tm_sec);
tm.tm_year -= 1900;
tm.tm_mon--;
tm.tm_isdst = 0;
return mktime(&tm);
}
void time_str(time_t tt, char *s)
{
struct tm *tp;
tp = localtime(&tt);
strftime(s, 15, "%Y%m%d%H%M%S", tp);
return;
}
void DateEx(char *t, int n)
{
char s[15];
time_t tm;
tm = str_time(t);
tm += (time_t) n;
time_str(tm, s);
puts(s);
return;
}
int main(void)
{
DateEx("20080827235925", 40);
return 0;
}
|
java.util.Calendar#addを使ってみました。
これといった捻りは特になしです。
horiuchiさん(#7513)がJavaで投稿したもののGroovy版といった位置づけですかね。
1 2 3 4 5 6 7 | def dateEx(date = null, delta) {
def format = new java.text.SimpleDateFormat('yyyyMMddHHmmss')
def cal = Calendar.instance
if (date) { cal.time = format.parse(date) }
cal.add(Calendar.SECOND, delta)
return format.format(cal.time)
}
|
1 2 3 4 | fun addDate (time, sec) = Date.toString (Date.fromTimeLocal (Time.+ (Time.fromSeconds sec, Date.toTime (valOf (Date.fromString time)))));
print (addDate ("Tue Sep 02 10:20:30 2008", 15) ^ "\n");
print (addDate ("Tue Sep 02 10:20:30 2008", ~5) ^ "\n");
|
SQL Server 2008 で確認しました。
1 2 3 4 5 6 7 8 | WITH
Input(d, n) AS (
SELECT '2008-8-27 23:59:25', 40
)
, DateEx(d) AS (
SELECT DATEADD(S, COALESCE(n, 0), d) FROM Input
)
SELECT d FROM DateEx
|






raynstard
#7401()
Rating0/0=0.00
日時を表す文字列と時間(秒)を受け取り 指定された日時からN秒となる日時を出力する関数 DateEx() を作成してください。 関数の仕様は次の通りです。 1. 入力となる日時の書式は任意である。 → プログラムの都合に合わせてよい。 2. 入力となる時間(秒)は、負の値も許容すること。 また、負の値が指定された場合、指定の日時よりも前の日時を出力すること 3. 出力する日時は入力の日時と同じ書式をとる文字列であること 4. 出力する日時は正規化されていること 5. 出力先は標準出力、または、バッファのいずれでもよい。 たとえば、DateEx("20080827235925",40)ならば 出力は 「20080828000005」です。 余力があれば時間を省略可能とし、 省略された場合は「現在時刻」を利用するようにしてみてください。1 reply [ reply ]